How to implement 3 stacks with one array? - algorithm

Sometimes, I come across the following interview question: How to implement 3 stacks with one array ? Of course, any static allocation is not a solution.

Space (not time) efficient. You could:
1) Define two stacks beginning at the array endpoints and growing in opposite directions.
2) Define the third stack as starting in the middle and growing in any direction you want.
3) Redefine the Push op, so that when the operation is going to overwrite other stack, you shift the whole middle stack in the opposite direction before Pushing.
You need to store the stack top for the first two stacks, and the beginning and end of the third stack in some structure.
Edit
Above you may see an example. The shifting is done with an equal space partitioning policy, although other strategies could be chosen depending upon your problem heuristics.
Edit
Following #ruslik's suggestion, the middle stack could be implemented using an alternating sequence for subsequent pushes. The resulting stack structure will be something like:
| Elem 6 | Elem 4 | Elem 2 | Elem 0 | Elem 1 | Elem 3 | Elem 5 |
In this case, you'll need to store the number n of elements on the middle stack and use the function:
f[n_] := 1/4 ( (-1)^n (-1 + 2 n) + 1) + BS3
to know the next array element to use for this stack.
Although probably this will lead to less shifting, the implementation is not homogeneous for the three stacks, and inhomogeneity (you know) leads to special cases, more bugs and difficulties to maintain code.

As long as you try to arrange all items from one stack together at one "end" of the array, you're lacking space for the third stack.
However, you could "intersperse" the stack elements. Elements of the first stack are at indices i * 3, elements of the second stack are at indices i * 3 + 1, elements of the third stack are at indices i * 3 + 2 (where i is an integer).
+----+----+----+----+----+----+----+----+----+----+----+----+----+..
| A1 : B1 : C1 | A2 : B2 : C2 | : B3 | C3 | : B4 : | :
+----+----+----+----+----+----+----+----+----+----+----+----+----+..
^ ^ ^
A´s top C´s top B´s top
Of course, this scheme is going to waste space, especially when the stacks have unequal sizes. You could create arbitrarily complex schemes similar to the one described above, but without knowing any more constraints for the posed question, I'll stop here.
Update:
Due to the comments below, which do have a very good point, it should be added that interspersing is not necessary, and may even degrade performance when compared to a much simpler memory layout such as the following:
+----+----+----+----+----+----+----+----+----+----+----+----+----+..
| A1 : A2 : : : | B1 : B2 : B3 : B4 : | C1 : C2 : C3 :
+----+----+----+----+----+----+----+----+----+----+----+----+----+..
^ ^ ^
A´s top B´s top C´s top
i.e. giving each stack it's own contiguous block of memory. If the real question is indeed to how to make the best possible use of a fixed amount of memory, in order to not limit each stack more than necessary, then my answer isn't going to be very helpful.
In that case, I'd go with #belisarius' answer: One stack goes to the "bottom" end of the memory area, growing "upwards"; another stack goes to the "top" end of the memory area, growing "downwards", and one stack is in the middle that grows in any direction but is able to move when it gets too close to one of the other stacks.

Maintain a single arena for all three stacks. Each element pushed onto the stack has a backwards pointer to its previous element. The bottom of each stack has a pointer to NULL/None.
The arena maintains a pointer to the next item in the free space. A push adds this element to the respective stack and marks it as no longer in the free space. A pop removes the element from the respective stack and adds it to the free list.
From this sketch, elements in stacks need a reverse pointer and space for the data. Elements in the free space need two pointers, so the free space is implemented as a doubly linked list.
The object containing the three stacks needs a pointer to the top of each stack plus a pointer to the head of the free list.
This data structure uses all the space and pushes and pops in constant time. There is overhead of a single pointer for all data elements in a stack and the free list elements use the maximum of (two pointers, one pointer + one element).
Later: python code goes something like this. Note use of integer indexes as pointers.
class StackContainer(object):
def __init__(self, stack_count=3, size=256):
self.stack_count = stack_count
self.stack_top = [None] * stack_count
self.size = size
# Create arena of doubly linked list
self.arena = [{'prev': x-1, 'next': x+1} for x in range(self.size)]
self.arena[0]['prev'] = None
self.arena[self.size-1]['next'] = None
self.arena_head = 0
def _allocate(self):
new_pos = self.arena_head
free = self.arena[new_pos]
next = free['next']
if next:
self.arena[next]['prev'] = None
self.arena_head = next
else:
self.arena_head = None
return new_pos
def _dump(self, stack_num):
assert 0 <= stack_num < self.stack_count
curr = self.stack_top[stack_num]
while curr is not None:
d = self.arena[curr]
print '\t', curr, d
curr = d['prev']
def _dump_all(self):
print '-' * 30
for i in range(self.stack_count):
print "Stack %d" % i
self._dump(i)
def _dump_arena(self):
print "Dump arena"
curr = self.arena_head
while curr is not None:
d = self.arena[curr]
print '\t', d
curr = d['next']
def push(self, stack_num, value):
assert 0 <= stack_num < self.stack_count
# Find space in arena for new value, update pointers
new_pos = self._allocate()
# Put value-to-push into a stack element
d = {'value': value, 'prev': self.stack_top[stack_num], 'pos': new_pos}
self.arena[new_pos] = d
self.stack_top[stack_num] = new_pos
def pop(self, stack_num):
assert 0 <= stack_num < self.stack_count
top = self.stack_top[stack_num]
d = self.arena[top]
assert d['pos'] == top
self.stack_top[stack_num] = d['prev']
arena_elem = {'prev': None, 'next': self.arena_head}
# Link the current head to the new head
head = self.arena[self.arena_head]
head['prev'] = top
# Set the curr_pos to be the new head
self.arena[top] = arena_elem
self.arena_head = top
return d['value']
if __name__ == '__main__':
sc = StackContainer(3, 10)
sc._dump_arena()
sc.push(0, 'First')
sc._dump_all()
sc.push(0, 'Second')
sc.push(0, 'Third')
sc._dump_all()
sc.push(1, 'Fourth')
sc._dump_all()
print sc.pop(0)
sc._dump_all()
print sc.pop(1)
sc._dump_all()

I have a solution for this question. The following program makes the best use of the array (in my case, an array of StackNode Objects). Let me know if you guys have any questions about this. [It's pretty late out here, so i didn't bother to document the code - I know, I should :) ]
public class StackNode {
int value;
int prev;
StackNode(int value, int prev) {
this.value = value;
this.prev = prev;
}
}
public class StackMFromArray {
private StackNode[] stackNodes = null;
private static int CAPACITY = 10;
private int freeListTop = 0;
private int size = 0;
private int[] stackPointers = { -1, -1, -1 };
StackMFromArray() {
stackNodes = new StackNode[CAPACITY];
initFreeList();
}
private void initFreeList() {
for (int i = 0; i < CAPACITY; i++) {
stackNodes[i] = new StackNode(0, i + 1);
}
}
public void push(int stackNum, int value) throws Exception {
int freeIndex;
int currentStackTop = stackPointers[stackNum - 1];
freeIndex = getFreeNodeIndex();
StackNode n = stackNodes[freeIndex];
n.prev = currentStackTop;
n.value = value;
stackPointers[stackNum - 1] = freeIndex;
}
public StackNode pop(int stackNum) throws Exception {
int currentStackTop = stackPointers[stackNum - 1];
if (currentStackTop == -1) {
throw new Exception("UNDERFLOW");
}
StackNode temp = stackNodes[currentStackTop];
stackPointers[stackNum - 1] = temp.prev;
freeStackNode(currentStackTop);
return temp;
}
private int getFreeNodeIndex() throws Exception {
int temp = freeListTop;
if (size >= CAPACITY)
throw new Exception("OVERFLOW");
freeListTop = stackNodes[temp].prev;
size++;
return temp;
}
private void freeStackNode(int index) {
stackNodes[index].prev = freeListTop;
freeListTop = index;
size--;
}
public static void main(String args[]) {
// Test Driver
StackMFromArray mulStack = new StackMFromArray();
try {
mulStack.push(1, 11);
mulStack.push(1, 12);
mulStack.push(2, 21);
mulStack.push(3, 31);
mulStack.push(3, 32);
mulStack.push(2, 22);
mulStack.push(1, 13);
StackNode node = mulStack.pop(1);
node = mulStack.pop(1);
System.out.println(node.value);
mulStack.push(1, 13);
} catch (Exception e) {
e.printStackTrace();
}
}
}

For simplicity if not very efficient memory usage, you could[*] divide the array up into list nodes, add them all to a list of free nodes, and then implement your stacks as linked lists, taking nodes from the free list as required. There's nothing special about the number 3 in this approach, though.
[*] in a low-level language where memory can be used to store pointers, or if the stack elements are of a type such as int that can represent an index into the array.

There are many solutions to this problem already stated on this page. The fundamental questions, IMHO are:
How long does each push/pop operation take?
How much space is used? Specifically, what is the smallest number of elements that can be pushed to the three stacks to cause the data structure to run out of space?
As far as I can tell, each solution already posted on this page either can take up to linear time for a push/pop or can run out of space with a linear number of spaces still empty.
In this post, I will reference solutions that perform much better, and I will present the simplest one.
In order to describe the solution space more carefully, I will refer to two functions of a data structure in the following way:
A structure that takes O(f(n)) amortized time to perform a push/pop and does not run out of space unless the three stacks hold at least n - O(g(n)) items will be referred to as an (f,g) structure. Smaller f and g are better. Every structure already posted on this page has n for either the time or the space. I will demonstrate a (1,√n) structure.
This is all based on:
Michael L. Fredman and Deborah L. Goldsmith, "Three Stacks", in Journal of Algorithms, Volume 17, Issue 1, July 1994, Pages 45-70
An earlier version appeared in the 29th Annual Symposium on Foundations of Computer Science (FOCS) in 1988
Deborah Louise Goldsmith's PhD thesis from University of California, San Diego, Department of Electrical Engineering/Computer Science in 1987, "Efficient memory management for >= 3 stacks"
They show, though I will not present, a (log n/log S,S) structure for any S. This is equivalent to a (t, n1/t) structure for any t. I will show a simplified version that is a (1,√n) structure.
Divide the array up into blocks of size Θ(√n). The blocks are numbered from 1 to Θ(√n), and the number of a block is called its "address". An address can be stored in an array slot instead of a real item. An item within a given block can be referred to with a number less than O(√n), and such a number is called an index. An index will also fit in an array slot.
The first block will be set aside for storing addresses and indexes, and no other block will store any addresses or indexes. The first block is called the directory. Every non-directory block will either be empty or hold elements from just one of the three stacks; that is, no block will have two elements from different stacks. Additionally, every stack will have at most one block that is partially filled -- all other blocks associated with a stack will be completely full or completely empty.
As long as there is an empty block, a push operation will be permitted to any stack. Pop operations are always permitted. When a push operation fails, the data structure is full. At that point, the number of slots not containing elements from one of the stacks is at most O(√n): two partially-filled blocks from the stacks not being pushed to, and one directory block.
Every block is ordered so that the elements closer to the front of the block (lower indexes) are closer to the bottom of the stack.
The directory holds:
Three addresses for the blocks at the top of the three stacks, or 0 if there are no blocks in a particular stack yet
Three indexes for the element at the top of the three stacks, or 0 if there are no items in a particular stack yet.
For each full or partially full block, the address of the block lower than it in the same stack, or 0 if it is the lowest block in the stack.
The address of a free block, called the leader block, or 0 if there are no free blocks
For each free block, the address of another free block, or 0 if there are no more free blocks
These last two constitute a stack, stored as a singly-linked list, of free blocks. That is, following the addresses of free blocks starting with the leader block will give a path through all the free blocks, ending in a 0.
To push an item onto a stack, find its top block and top element within that block using the directory. If there is room in that block, put the item there and return.
Otherwise, pop the stack of free blocks by changing the address of the leader block to the address of the next free block in the free block stack. Change the address and index for the stack to be the address of the just-popped free block and 1, respectively. Add the item to the just-popped block at index 1, and return.
All operations take O(1) time. Pop is symmetric.

A variant on an earlier answer: stack #1 grows from the left, and stack #2 grows from the right.
Stack #3 is in the center, but the elements grow in alternate order to the left and right. If N is the center index, the stack grows as: N, N-1, N+1, N-2, N+2, etc. A simple function converts the stack index to an array index.

I think you should divide array in 3 pieces, making head of first stack at 0, head of second stack at n/3, head of 3rd stack at n-1.
so implement push operation on :
first & second stack make i++ and for 3rd stack make i--;
If you encounter that first stack have no space to push, shift 2nd stack k/3 positions forward. Where k is the number of positions left to be filled in array.
If you encounter that second stack have no space to push, shift 2nd stack 2*k/3 positions backward. Where k is the number of positions left to be filled in array.
If you encounter that third stack have no space to push, shift 2nd stack 2*k/3 positions backward. Where k is the number of positions left to be filled in array.
We are shifting k/3 and 2*k/3 when no space is left so that after shifting of middle stack, each stack have equal space available for use.

Store the stack in the area in such way when first stack goes into index 0, then 0+3=3, then 3+3=6...; the second one goes into indexes 1, 1+3=4, 4+3=7...; the the third one goes into indexes 2, 2+3=5, 5+3=8
So if we mark the first stack elements with a, as one with b and there with c we get:
a1 b1 c1 a2 b2 c2 a3 b3 c3...
There could be gaps but we always know the top indexes which are stored in 3-element topIndex array.

Partitioning the array into 3 parts in not a good idea as it will give overflow if there are many elements in stack1 and very few elements in the other two.
My idea:
Keep three pointers ptr1, ptr2, ptr3 to point the top element of respective stacks.
Initially ptr1 = ptr2 = ptr3 = -1;
In the array, the even indexed element will store the value and odd indexed element will store the index of previous element of that stack.
For example,
s1.push(1);
s2.push(4);
s3.push(3);
s1.push(2);
s3.push(7);
s1.push(10);
s1.push(5);
then our array looks like:
1, -1, 4, -1, 3, -1, 2, 0, 7, 4, 10, 6, 5, 10
and the values of pointers are:
ptr1 = 12, ptr2 = 2 , ptr3 = 8

Solution: Implementing two stacks is easy.
First stack grows from start to end while second one grows from end to start.
Overflow for any of them will not happen unless there really is no space left on the array.
For three stacks, following is required:
An auxiliary array to maintain the parent for each node.
Variables to store the current top of each stack.
With these two in place, data from all the stacks can be interspersed in the original array and one can still do push/pop/size operations for all the stacks.
When inserting any element, insert it at the end of all the elements in the normal array.
Store current-top of that stack as parent for the new element (in the parents' array) and update current-top to the new position.
When deleting, insert NULL in the stacks array for the deleted element and reset stack-top for that stack to the parent.
When the array is full, it will have some holes corresponding to deleted elements.
At this point, either the array can be compacted to bring all free space together or a linear search can be done for free space when inserting new elements.
for further details refer this link:- https://coderworld109.blogspot.in/2017/12/how-to-implement-3-stacks-with-one-array.html

Here is my solution of N stacks in a single array.
Some constraints will be here.
that size of the array will not be less than of the number of stacks.
I have used to customize exception class StackException in my solution. You can change the exception class for running the programme.
For multiple stacks in an array, I managed pointers to another array.
package com.practice.ds.stack;
import java.util.Scanner;
import java.util.logging.Logger;
/** Multiple stacks in a single array */
public class MultipleStack {
private static Logger logger = Logger.getLogger("MultipleStack");
private int[] array;
private int size = 10;
private int stackN = 1;
private int[] pointer;
public MultipleStack() {
this.array = new int[size];
this.pointer = new int[1];
}
public MultipleStack(int size, int stackN) throws StackException {
if (stackN > size)
throw new StackException("Input mismatch ! no of stacks can't be larger than size ");
this.size = size;
this.stackN = stackN;
init();
}
private void init() {
if (size <= 0) {
logger.info("Initialize size is " + size + " so assiginig defalt size ");
this.size = 10;
}
if (stackN < 1) {
logger.info("Initialize no of Stack is " + size + " so assiginig defalt");
this.stackN = 1;
}
this.array = new int[size];
this.pointer = new int[stackN];
initializePointer();
}
private void initializePointer() {
for (int i = 0; i < stackN; i++)
pointer[i] = (int)(i * Math.ceil(size / stackN) - 1);
}
public void push(int item, int sn) throws StackException {
if (full(sn))
throw new StackException(sn + " is overflowed !");
int stkPointer = pointer[sn - 1];
array[++stkPointer] = item;
pointer[sn - 1] = stkPointer;
}
public void pop(int sn) throws StackException {
if (empty(sn))
throw new StackException(sn + " is underflow !");
int peek = peek(sn);
System.out.println(peek);
pointer[sn - 1] = --pointer[sn - 1];
}
public int peek(int sn) throws StackException {
authenticate(sn);
return array[pointer[sn - 1]];
}
public boolean empty(int sn) throws StackException {
authenticate(sn);
return pointer[sn - 1] == (int)(((sn - 1) * Math.ceil(size / stackN)) - 1);
}
public boolean full(int sn) throws StackException {
authenticate(sn);
return sn == stackN ? pointer[sn - 1] == size - 1 : pointer[sn - 1] == (int)((sn) * Math.ceil(size / stackN)) - 1;
}
private void authenticate(int sn) throws StackException {
if (sn > stackN || sn < 1)
throw new StackException("No such stack found");
}
public static void main(String[] args) {
try (Scanner scanner = new Scanner(System.in)) {
System.out.println("Define size of the stack");
int size = scanner.nextInt();
System.out.println("total number of stacks");
int stackN = scanner.nextInt();
MultipleStack stack = new MultipleStack(size, stackN);
boolean exit = false;
do {
System.out.println("1. Push");
System.out.println("2. Pop");
System.out.println("3. Exit");
System.out.println("Choice");
int choice = scanner.nextInt();
switch (choice) {
case 1:
try {
System.out.println("Item : ");
int item = scanner.nextInt();
System.out.println("Stack Number : ");
int stk = scanner.nextInt();
stack.push(item, stk);
} catch (Exception e) {
e.printStackTrace();
}
break;
case 2:
try {
System.out.println("Stack Number : ");
int stk = scanner.nextInt();
stack.pop(stk);
} catch (Exception e) {
e.printStackTrace();
}
break;
case 3:
exit = true;
break;
default:
System.out.println("Invalid choice !");
break;
}
} while (!exit);
} catch (Exception e) {
e.printStackTrace();
}
}
}

We can generalize it to K stacks in one Array. Basic idea is to:
Maintain a PriorityQueue as a min heap of currently free indexes in the allocation array.
Maintain an array of size K, that holds the top of the stack, for each of the stacks.
Create a Data class with 1) Value 2) Index of Prev element in the allocation array 3) Index of current element being pushed in the
allocation array
Maintain an allocation array of type Data
Refer the code for a working sample implementation.
import java.util.*;
public class Main
{
// A Java class to represent k stacks in a single array of size n
public static final class KStack {
/**
* PriorityQueue as min heap to keep track of the next free index in the
* backing array.
*/
private final PriorityQueue<Integer> minHeap = new PriorityQueue<>((a,b) -> (a - b));
/**
* Keeps track of the top of the stack of each of the K stacks
*/
private final Data index[];
/**
* Backing array to hold the data of K stacks.
*/
private final Data array[];
public KStack(int noOfStacks, int sizeOfBackingArray) {
index = new Data[noOfStacks];
array = new Data[sizeOfBackingArray];
for(int i =0; i< sizeOfBackingArray; i++) {
minHeap.add(i);
}
}
public void push(int val, int stackNo) {
if(minHeap.isEmpty()) {
return;
}
int nextFreeIdx = minHeap.poll();
Data tos = index[stackNo];
if(tos == null) {
tos = new Data(val, -1 /* Previous elemnet's idx*/, nextFreeIdx
/* This elemnent's idx in underlying array*/);
} else {
tos = new Data(val, tos.myIndex, nextFreeIdx);
}
index[stackNo] = tos;
array[nextFreeIdx] = tos;
}
public int pop(int stackNo) {
if(minHeap.size() == array.length) {
return -1; // Maybe throw Exception?
}
Data tos = index[stackNo];
if(tos == null) {
return -1; // Maybe throw Exception?
}
minHeap.add(tos.myIndex);
array[tos.myIndex] = null;
int value = tos.value;
if(tos.prevIndex == -1) {
tos = null;
} else {
tos = array[tos.prevIndex];
}
index[stackNo] = tos;
return value;
}
}
public static final class Data {
int value;
int prevIndex;
int myIndex;
public Data(int value, int prevIndex, int myIndex) {
this.value = value;
this.prevIndex = prevIndex;
this.myIndex = myIndex;
}
#Override
public String toString() {
return "Value: " + this.value + ", prev: " + this.prevIndex + ", myIndex: " + myIndex;
}
}
// Driver program
public static void main(String[] args)
{
int noOfStacks = 3, sizeOfBackingArray = 10;
KStack ks = new KStack(noOfStacks, sizeOfBackingArray);
// Add elements to stack number 1
ks.push(11, 0);
ks.push(9, 0);
ks.push(7, 0);
// Add elements to stack number 3
ks.push(51, 2);
ks.push(54, 2);
// Add elements to stack number 2
ks.push(71, 1);
ks.push(94, 1);
ks.push(93, 1);
System.out.println("Popped from stack 3: " + ks.pop(2));
System.out.println("Popped from stack 3: " + ks.pop(2));
System.out.println("Popped from stack 3: " + ks.pop(2));
System.out.println("Popped from stack 2: " + ks.pop(1));
System.out.println("Popped from stack 1: " + ks.pop(0));
}
}

Dr. belisarius's answer explains the basic algorithm, but doesn't go in the details, and as we know, the devil is always in the details. I coded up a solution in Python 3, with some explanation and a unit test. All operations run in constant time, as they should for a stack.
# One obvious solution is given array size n, divide up n into 3 parts, and allocate floor(n / 3) cells
# to two stacks at either end of the array, and remaining cells to the one in the middle. This strategy is not
# space efficient because even though there may be space in the array, one of the stack may overflow.
#
# A better approach is to have two stacks at either end of the array, the left one growing on the right, and the
# right one growing on the left. The middle one starts at index floor(n / 2), and grows at both ends. When the
# middle stack size is even, it grows on the right, and when it's odd, it grows on the left. This way, the middle
# stack grows evenly and minimizes the changes of overflowing one of the stack at either end.
#
# The rest is pointer arithmetic, adjusting tops of the stacks on push and pop operations.
class ThreeStacks:
def __init__(self, n: int):
self._arr: List[int] = [0] * n
self._tops: List[int] = [-1, n, n // 2]
self._sizes: List[int] = [0] * 3
self._n = n
def _is_stack_3_even_size(self):
return self._sizes[2] % 2 == 0
def _is_stack_3_odd_size(self):
return not self._is_stack_3_even_size()
def is_empty(self, stack_number: int) -> bool:
return self._sizes[stack_number] == 0
def is_full(self, stack_number: int) -> bool:
if stack_number == 0 and self._is_stack_3_odd_size():
return self._tops[stack_number] == self._tops[2] - self._sizes[2]
elif stack_number == 1 and self._is_stack_3_even_size():
return self._tops[stack_number] == self._tops[2] + self._sizes[2]
return (self._is_stack_3_odd_size() and self._tops[0] == self._tops[2] - self._sizes[2]) or \
(self._is_stack_3_even_size() and self._tops[1] == self._tops[2] + self._sizes[2])
def pop(self, stack_number: int) -> int:
if self.is_empty(stack_number):
raise RuntimeError(f"Stack : {stack_number} is empty")
x: int = self._arr[self._tops[stack_number]]
if stack_number == 0:
self._tops[stack_number] -= 1
elif stack_number == 1:
self._tops[stack_number] += 1
else:
if self._is_stack_3_even_size():
self._tops[stack_number] += (self._sizes[stack_number] - 1)
else:
self._tops[stack_number] -= (self._sizes[stack_number] - 1)
self._sizes[stack_number] -= 1
return x
def push(self, item: int, stack_number: int) -> None:
if self.is_full(stack_number):
raise RuntimeError(f"Stack: {stack_number} is full")
if stack_number == 0:
self._tops[stack_number] += 1
elif stack_number == 1:
self._tops[stack_number] -= 1
else:
if self._is_stack_3_even_size():
self._tops[stack_number] += self._sizes[stack_number]
else:
self._tops[stack_number] -= self._sizes[stack_number]
self._arr[self._tops[stack_number]] = item
self._sizes[stack_number] += 1
def __repr__(self):
return str(self._arr)
Test:
def test_stack(self):
stack = ThreeStacks(10)
for i in range(3):
with pytest.raises(RuntimeError):
stack.pop(i)
for i in range(1, 4):
stack.push(i, 0)
for i in range(4, 7):
stack.push(i, 1)
for i in range(7, 11):
stack.push(i, 2)
for i in range(3):
with pytest.raises(RuntimeError):
stack.push(1, i)
assert [stack.pop(i) for i in range(3)] == [3, 6, 10]
assert [stack.pop(i) for i in range(3)] == [2, 5, 9]
assert [stack.pop(i) for i in range(3)] == [1, 4, 8]
for i in range(2):
assert stack.is_empty(i)
assert not stack.is_empty(2)
assert stack.pop(2) == 7
assert stack.is_empty(2)

This is a very common interview question "Implement 3 stacks using a single Array or >List".
Here is my solution-
Approach 1- Go for a fixed division of an array means if we divide our array into 3 equal parts and push the elements of an array
into three fixed-sized stacks.
For stack 1, use [0,n/3]
For stack 2, use [n/3,2n/3]
For stack 3, use [2n/3,n]. The problem with this approach is that we may face a condition where the size of an array may be
greater than the size of the stack ie. Stack Overflow condition. So,
we must take care of special cases and edge cases like this. now go
for 2nd approach.
Approach 2- Flexible Division, In the first approach we face a condition where the size of an array may be greater than the size of
the stack ie the Stack overflow condition. we can overcome this
problem by doing a flexible division of the stack. while adding
elements to the stack, when one stack exceeds the initial capacity,
shift the elements to the next stack. So, this way we can approach
this problem.

Here's my solution for it in C# -
/* Program: Implement 3 stacks using a single array
*
* Date: 12/26/2015
*/
using System;
namespace CrackingTheCodingInterview
{
internal class Item
{
public object data;
public int prev;
}
/// <summary>
/// Class implementing 3 stacks using single array
/// </summary>
public class Stacks
{
/// <summary>
/// Pushing an element 'data' onto a stack 'i'
/// </summary>
public void Push(int i, object d)
{
i--;
if (available != null)
{
int ava = (int)available.DeleteHead();
elems[ava].data = d;
elems[ava].prev = top[i];
top[i] = ava;
}
else
{
Console.WriteLine("Array full. No more space to enter!");
return;
}
}
/// <summary>
/// Popping an element from stack 'i'
/// </summary>
public object Pop(int i)
{
i--;
if (top[i] != -1)
{
object popVal = elems[top[i]].data;
int prevTop = elems[top[i]].prev;
elems[top[i]].data = null;
elems[top[i]].prev = -1;
available.Insert(top[i]);
top[i] = prevTop;
return popVal;
}
else
{
Console.WriteLine("Stack: {0} empty!", i);
return null;
}
}
/// <summary>
/// Peeking top element of a stack
/// </summary>
public object Peek(int i)
{
i--;
if (top[i] != -1)
{
return elems[top[i]].data;
}
else
{
Console.WriteLine("Stack: {0} empty!", i);
return null;
}
}
/// <summary>
/// Constructor initializing array of Nodes of size 'n' and the ability to store 'k' stacks
/// </summary>
public Stacks(int n, int k)
{
elems = new Item[n];
top = new int[k];
for (int i = 0; i < k; i++)
{
top[i] = -1;
}
for (int i = 0; i < n; i++)
{
elems[i] = new Item();
elems[i].data = null;
elems[i].prev = -1;
}
available = new SinglyLinkedList();
for (int i = n - 1; i >= 0; i--)
{
available.Insert(i);
}
}
private Item[] elems;
private int[] top;
private SinglyLinkedList available;
}
internal class StacksArrayTest
{
static void Main()
{
Stacks s = new Stacks(10, 3);
s.Push(1, 'a');
s.Push(1, 'b');
s.Push(1, 'c');
Console.WriteLine("After pushing in stack 1");
Console.WriteLine("Top 1: {0}", s.Peek(1));
s.Push(2, 'd');
s.Push(2, 'e');
s.Push(2, 'f');
s.Push(2, 'g');
Console.WriteLine("After pushing in stack 2");
Console.WriteLine("Top 1: {0}", s.Peek(1));
Console.WriteLine("Top 2: {0}", s.Peek(2));
s.Pop(1);
s.Pop(2);
Console.WriteLine("After popping from stack 1 and 2");
Console.WriteLine("Top 1: {0}", s.Peek(1));
Console.WriteLine("Top 2: {0}", s.Peek(2));
s.Push(3, 'h');
s.Push(3, 'i');
s.Push(3, 'j');
s.Push(3, 'k');
s.Push(3, 'l');
Console.WriteLine("After pushing in stack 3");
Console.WriteLine("Top 3: {0}", s.Peek(3));
Console.ReadLine();
}
}
}
Output:
After pushing in stack 1
Top 1: c
After pushing in stack 2
Top 1: c
Top 2: g
After popping from stack 1 and 2
Top 1: b
Top 2: f
After pushing in stack 3
Top 3: l
I refer to this post for coding it - http://codercareer.blogspot.com/2013/02/no-39-stacks-sharing-array.html

package job.interview;
import java.util.Arrays;
public class NStack1ArrayGen<T> {
T storage[];
int numOfStacks;
Integer top[];
public NStack1ArrayGen(int numOfStks, T myStorage[]){
storage = myStorage;
numOfStacks = numOfStks;
top = new Integer[numOfStks];
for(int i=0;i<numOfStks;i++){top[i]=-1;}
}
public void push(int stk_indx, T value){
int r_indx = stk_indx -1;
if(top[r_indx]+numOfStacks < storage.length){
top[r_indx] = top[r_indx] < 0 ? stk_indx-1 : top[r_indx]+numOfStacks;
storage[top[r_indx]] = value;
}
}
public T pop(int stk_indx){
T ret = top[stk_indx-1]<0 ? null : storage[top[stk_indx-1]];
top[stk_indx-1] -= numOfStacks;
return ret;
}
public void printInfo(){
print("The array", Arrays.toString(storage));
print("The top indices", Arrays.toString(top));
for(int j=1;j<=numOfStacks;j++){
printStack(j);
}
}
public void print(String name, String value){
System.out.println(name + " ==> " + value);
}
public void printStack(int indx){
String str = "";
while(top[indx-1]>=0){
str+=(str.length()>0 ? "," : "") + pop(indx);
}
print("Stack#"+indx,str);
}
public static void main (String args[])throws Exception{
int count=4, tsize=40;
int size[]={105,108,310,105};
NStack1ArrayGen<String> mystack = new NStack1ArrayGen<String>(count,new String[tsize]);
for(int i=1;i<=count;i++){
for(int j=1;j<=size[i-1];j++){
mystack.push(i, "stk"+i+"_value"+j);
}
}
}
}
This prints:
The array ==> [stk1_value1, stk2_value1, stk3_value1, stk4_value1, stk1_value2, stk2_value2, stk3_value2, stk4_value2, stk1_value3, stk2_value3, stk3_value3, stk4_value3, stk1_value4, stk2_value4, stk3_value4, stk4_value4, stk1_value5, stk2_value5, stk3_value5, stk4_value5, stk1_value6, stk2_value6, stk3_value6, stk4_value6, stk1_value7, stk2_value7, stk3_value7, stk4_value7, stk1_value8, stk2_value8, stk3_value8, stk4_value8, stk1_value9, stk2_value9, stk3_value9, stk4_value9, stk1_value10, stk2_value10, stk3_value10, stk4_value10]
The top indices ==> [36, 37, 38, 39]
Stack#1 ==> stk1_value10,stk1_value9,stk1_value8,stk1_value7,stk1_value6,stk1_value5,stk1_value4,stk1_value3,stk1_value2,stk1_value1
Stack#2 ==> stk2_value10,stk2_value9,stk2_value8,stk2_value7,stk2_value6,stk2_value5,stk2_value4,stk2_value3,stk2_value2,stk2_value1
Stack#3 ==> stk3_value10,stk3_value9,stk3_value8,stk3_value7,stk3_value6,stk3_value5,stk3_value4,stk3_value3,stk3_value2,stk3_value1
Stack#4 ==> stk4_value10,stk4_value9,stk4_value8,stk4_value7,stk4_value6,stk4_value5,stk4_value4,stk4_value3,stk4_value2,stk4_value1

enum stackId{LEFT, MID, RIGHT };
class threeStacks {
int* arr;
int leftSize;
int rightSize;
int midSize;
int mid;
int maxSize;
public:
threeStacks(int n):leftSize(0), rightSize(0), midSize(0), mid(n/2), maxSize(n)
{
arr = new int[n];
}
void push(stackId sid, int val){
switch(sid){
case LEFT:
pushLeft(val);
break;
case MID:
pushMid(val);
break;
case RIGHT:
pushRight(val);
}
}
int pop(stackId sid){
switch(sid){
case LEFT:
return popLeft();
case MID:
return popMid();
case RIGHT:
return popRight();
}
}
int top(stackId sid){
switch(sid){
case LEFT:
return topLeft();
case MID:
return topMid();
case RIGHT:
return topRight();
}
}
void pushMid(int val){
if(midSize+leftSize+rightSize+1 > maxSize){
cout << "Overflow!!"<<endl;
return;
}
if(midSize % 2 == 0){
if(mid - ((midSize+1)/2) == leftSize-1){
//left side OverFlow
if(!shiftMid(RIGHT)){
cout << "Overflow!!"<<endl;
return;
}
}
midSize++;
arr[mid - (midSize/2)] = val;
}
else{
if(mid + ((midSize+1)/2) == (maxSize - rightSize)){
//right side OverFlow
if(!shiftMid(LEFT)){
cout << "Overflow!!"<<endl;
return;
}
}
midSize++;
arr[mid + (midSize/2)] = val;
}
}
int popMid(){
if(midSize == 0){
cout << "Mid Stack Underflow!!"<<endl;
return -1;
}
int val;
if(midSize % 2 == 0)
val = arr[mid - (midSize/2)];
else
val = arr[mid + (midSize/2)];
midSize--;
return val;
}
int topMid(){
if(midSize == 0){
cout << "Mid Stack Underflow!!"<<endl;
return -1;
}
int val;
if(midSize % 2 == 0)
val = arr[mid - (midSize/2)];
else
val = arr[mid + (midSize/2)];
return val;
}
bool shiftMid(stackId dir){
int freeSpace;
switch (dir){
case LEFT:
freeSpace = (mid - midSize/2) - leftSize;
if(freeSpace < 1)
return false;
if(freeSpace > 1)
freeSpace /= 2;
for(int i=0; i< midSize; i++){
arr[(mid - midSize/2) - freeSpace + i] = arr[(mid - midSize/2) + i];
}
mid = mid-freeSpace;
break;
case RIGHT:
freeSpace = maxSize - rightSize - (mid + midSize/2) - 1;
if(freeSpace < 1)
return false;
if(freeSpace > 1)
freeSpace /= 2;
for(int i=0; i< midSize; i++){
arr[(mid + midSize/2) + freeSpace - i] = arr[(mid + midSize/2) - i];
}
mid = mid+freeSpace;
break;
default:
return false;
}
}
void pushLeft(int val){
if(midSize+leftSize+rightSize+1 > maxSize){
cout << "Overflow!!"<<endl;
return;
}
if(leftSize == (mid - midSize/2)){
//left side OverFlow
if(!shiftMid(RIGHT)){
cout << "Overflow!!"<<endl;
return;
}
}
arr[leftSize] = val;
leftSize++;
}
int popLeft(){
if(leftSize == 0){
cout << "Left Stack Underflow!!"<<endl;
return -1;
}
leftSize--;
return arr[leftSize];
}
int topLeft(){
if(leftSize == 0){
cout << "Left Stack Underflow!!"<<endl;
return -1;
}
return arr[leftSize - 1];
}
void pushRight(int val){
if(midSize+leftSize+rightSize+1 > maxSize){
cout << "Overflow!!"<<endl;
return;
}
if(maxSize - rightSize - 1 == (mid + midSize/2)){
//right side OverFlow
if(!shiftMid(LEFT)){
cout << "Overflow!!"<<endl;
return;
}
}
rightSize++;
arr[maxSize - rightSize] = val;
}
int popRight(){
if(rightSize == 0){
cout << "Right Stack Underflow!!"<<endl;
return -1;
}
int val = arr[maxSize - rightSize];
rightSize--;
return val;
}
int topRight(){
if(rightSize == 0){
cout << "Right Stack Underflow!!"<<endl;
return -1;
}
return arr[maxSize - rightSize];
}
};

Python
class Stack:
def __init__(self):
self.pos_1 = 0
self.pos_2 = 1
self.pos_3 = 2
self.stack = [None, None, None]
def pop_1(self):
if self.pos_2 - 1 > 0:
to_ret = self.stack.pop(self.pos_1)
self.pos_2 -= 1
self.pos_3 -= 1
return to_ret
def push_1(self, value):
self.stack.insert(self.pos_1, value)
self.pos_2 += 1
self.pos_3 += 1
return None
def pop_2(self):
if self.pos_2 - 1 < self.pos_3:
to_ret = self.stack.pop(self.pos_2)
self.pos_3 -= 1
return to_ret
def push_2(self, value):
self.stack.insert(self.pos_2, value)
self.pos_3 += 1
return None
def pop_3(self):
if self.pos_3 - 1 > self.pos_2:
to_ret = self.stack.pop(self.pos_3)
return to_ret
def push_3(self, value):
self.stack.insert(self.pos_3, value)
return None
if __name__ == "__main__":
stack = Stack()
stack.push_2(22)
stack.push_1(1)
stack.push_1(2)
print stack.pop_1()
print stack.pop_1()
print stack.pop_2()
prints: 2 1 22

Related

Why Unrolled LinkedList is semi filled?

Going through all the articles related to the implementation of Unrolled LinkedList, it seems that based on the capacity we generate a threshold and if the elements increase beyond that we create another node and put the element in that node.
Threshold = (capacity/2)+1
But why are we not filling the array in Unrolled LinkedList to its full capacity and then creating another node? Why do we need a threshold and keep the array semi-filled?
Quoted from Geeks for Geeks - insertion in Unrolled Linked List:
/* Java program to show the insertion operation
* of Unrolled Linked List */
import java.util.Scanner;
import java.util.Random;
// class for each node
class UnrollNode {
UnrollNode next;
int num_elements;
int array[];
// Constructor
public UnrollNode(int n)
{
next = null;
num_elements = 0;
array = new int[n];
}
}
// Operation of Unrolled Function
class UnrollLinkList {
private UnrollNode start_pos;
private UnrollNode end_pos;
int size_node;
int nNode;
// Parameterized Constructor
UnrollLinkList(int capacity)
{
start_pos = null;
end_pos = null;
nNode = 0;
size_node = capacity + 1;
}
// Insertion operation
void Insert(int num)
{
nNode++;
// Check if the list starts from NULL
if (start_pos == null) {
start_pos = new UnrollNode(size_node);
start_pos.array[0] = num;
start_pos.num_elements++;
end_pos = start_pos;
return;
}
// Attaching the elements into nodes
if (end_pos.num_elements + 1 < size_node) {
end_pos.array[end_pos.num_elements] = num;
end_pos.num_elements++;
}
// Creation of new Node
else {
UnrollNode node_pointer = new UnrollNode(size_node);
int j = 0;
for (int i = end_pos.num_elements / 2 + 1;
i < end_pos.num_elements; i++)
node_pointer.array[j++] = end_pos.array[i];
node_pointer.array[j++] = num;
node_pointer.num_elements = j;
end_pos.num_elements = end_pos.num_elements / 2 + 1;
end_pos.next = node_pointer;
end_pos = node_pointer;
}
}
// Display the Linked List
void display()
{
System.out.print("\nUnrolled Linked List = ");
System.out.println();
UnrollNode pointer = start_pos;
while (pointer != null) {
for (int i = 0; i < pointer.num_elements; i++)
System.out.print(pointer.array[i] + " ");
System.out.println();
pointer = pointer.next;
}
System.out.println();
}
}
/* Main Class */
class UnrolledLinkedList_Check {
// Driver code
public static void main(String args[])
{
Scanner sc = new Scanner(System.in);
// create instance of Random class
Random rand = new Random();
UnrollLinkList ull = new UnrollLinkList(5);
// Perform Insertion Operation
for (int i = 0; i < 12; i++) {
// Generate random integers in range 0 to 99
int rand_int1 = rand.nextInt(100);
System.out.println("Entered Element is " + rand_int1);
ull.Insert(rand_int1);
ull.display();
}
}
}
why are we not filling the array in Unrolled LinkedList to its full capacity and then creating another node?
Actually, the code that is provided does fill the array to full capacity:
if (end_pos.num_elements + 1 < size_node) {
end_pos.array[end_pos.num_elements] = num;
end_pos.num_elements++;
}
The threshold is not used here. Only when the array reaches its capacity, the threshold plays a role as a new array gets created:
UnrollNode node_pointer = new UnrollNode(size_node);
int j = 0;
for (int i = end_pos.num_elements / 2 + 1; i < end_pos.num_elements; i++)
node_pointer.array[j++] = end_pos.array[i];
Here we see the second half of the full array is copied into the new array. We can imagine this process as splitting a block into two blocks -- much like happens in a B-tree.
This allows for fast insertion the next time a value needs to be inserted (not at the end, but) at a specific offset in that array. If it were left full, it would trigger a new block at each insertion into that array. By leaving slack space in an array, we ensure fast insertion for at least a few of the future insertions that happen to be in that array.
I think it is to ensure having at least 50% utilization.
The algorithm not only splits in half if an insert is done, but also redistributes content if it's utilized at less than 50%. I think the second part is key: if you don't do the first part, you can't add a check that redistributes if the node is underutilized because your newly created node would immediately break that.
If you don't do the redistribution at all you might end up with a situation where you have a lot of underutilized nodes.
My first intuition was the same as the other comment (to avoid creating new nodes every time) but this wouldn't necessarily be an issue if you always check the next node before creating a new node, so I'm not sure that sufficient as a reason? (But maybe I'm missing something here)

Paper cut algorithm

I want to create a function to determine the most number of pieces of paper on a parent paper size
The formula above is still not optimal. If using the above formula will only produce at most 32 cut/sheet.
I want it like below.
This seems to be a very difficult problem to solve optimally. See http://lagrange.ime.usp.br/~lobato/packing/ for a discussion of a 2008 paper claiming that the problem is believed (but not proven) to be NP-hard. The researchers found some approximation algorithms and implemented them on that website.
The following solution uses Top-Down Dynamic Programming to find optimal solutions to this problem. I am providing this solution in C#, which shouldn't be too hard to convert into the language of your choice (or whatever style of pseudocode you prefer). I have tested this solution on your specific example and it completes in less than a second (I'm not sure how much less than a second).
It should be noted that this solution assumes that only guillotine cuts are allowed. This is a common restriction for real-world 2D Stock-Cutting applications and it greatly simplifies the solution complexity. However, CS, Math and other programming problems often allow all types of cutting, so in that case this solution would not necessarily find the optimal solution (but it would still provide a better heuristic answer than your current formula).
First, we need a value-structure to represent the size of the starting stock, the desired rectangle(s) and of the pieces cut from the stock (this needs to be a value-type because it will be used as the key to our memoization cache and other collections, and we need to to compare the actual values rather than an object reference address):
public struct Vector2D
{
public int X;
public int Y;
public Vector2D(int x, int y)
{
X = x;
Y = y;
}
}
Here is the main method to be called. Note that all values need to be in integers, for the specific case above this just means multiplying everything by 100. These methods here require integers, but are otherwise are scale-invariant so multiplying by 100 or 1000 or whatever won't affect performance (just make sure that the values don't overflow an int).
public int SolveMaxCount1R(Vector2D Parent, Vector2D Item)
{
// make a list to hold both the item size and its rotation
List<Vector2D> itemSizes = new List<Vector2D>();
itemSizes.Add(Item);
if (Item.X != Item.Y)
{
itemSizes.Add(new Vector2D(Item.Y, Item.X));
}
int solution = SolveGeneralMaxCount(Parent, itemSizes.ToArray());
return solution;
}
Here is an example of how you would call this method with your parameter values. In this case I have assumed that all of the solution methods are part of a class called SolverClass:
SolverClass solver = new SolverClass();
int count = solver.SolveMaxCount1R(new Vector2D(2500, 3800), new Vector2D(425, 550));
//(all units are in tenths of a millimeter to make everything integers)
The main method calls a general solver method for this type of problem (that is not restricted to just one size rectangle and its rotation):
public int SolveGeneralMaxCount(Vector2D Parent, Vector2D[] ItemSizes)
{
// determine the maximum x and y scaling factors using GCDs (Greastest
// Common Divisor)
List<int> xValues = new List<int>();
List<int> yValues = new List<int>();
foreach (Vector2D size in ItemSizes)
{
xValues.Add(size.X);
yValues.Add(size.Y);
}
xValues.Add(Parent.X);
yValues.Add(Parent.Y);
int xScale = NaturalNumbers.GCD(xValues);
int yScale = NaturalNumbers.GCD(yValues);
// rescale our parameters
Vector2D parent = new Vector2D(Parent.X / xScale, Parent.Y / yScale);
var baseShapes = new Dictionary<Vector2D, Vector2D>();
foreach (var size in ItemSizes)
{
var reducedSize = new Vector2D(size.X / xScale, size.Y / yScale);
baseShapes.Add(reducedSize, reducedSize);
}
//determine the minimum values that an allowed item shape can fit into
_xMin = int.MaxValue;
_yMin = int.MaxValue;
foreach (var size in baseShapes.Keys)
{
if (size.X < _xMin) _xMin = size.X;
if (size.Y < _yMin) _yMin = size.Y;
}
// create the memoization cache for shapes
Dictionary<Vector2D, SizeCount> shapesCache = new Dictionary<Vector2D, SizeCount>();
// find the solution pattern with the most finished items
int best = solveGMC(shapesCache, baseShapes, parent);
return best;
}
private int _xMin;
private int _yMin;
The general solution method calls a recursive worker method that does most of the actual work.
private int solveGMC(
Dictionary<Vector2D, SizeCount> shapeCache,
Dictionary<Vector2D, Vector2D> baseShapes,
Vector2D sheet )
{
// have we already solved this size?
if (shapeCache.ContainsKey(sheet)) return shapeCache[sheet].ItemCount;
SizeCount item = new SizeCount(sheet, 0);
if ((sheet.X < _xMin) || (sheet.Y < _yMin))
{
// if it's too small in either dimension then this is a scrap piece
item.ItemCount = 0;
}
else // try every way of cutting this sheet (guillotine cuts only)
{
int child0;
int child1;
// try every size of horizontal guillotine cut
for (int c = sheet.X / 2; c > 0; c--)
{
child0 = solveGMC(shapeCache, baseShapes, new Vector2D(c, sheet.Y));
child1 = solveGMC(shapeCache, baseShapes, new Vector2D(sheet.X - c, sheet.Y));
if (child0 + child1 > item.ItemCount)
{
item.ItemCount = child0 + child1;
}
}
// try every size of vertical guillotine cut
for (int c = sheet.Y / 2; c > 0; c--)
{
child0 = solveGMC(shapeCache, baseShapes, new Vector2D(sheet.X, c));
child1 = solveGMC(shapeCache, baseShapes, new Vector2D(sheet.X, sheet.Y - c));
if (child0 + child1 > item.ItemCount)
{
item.ItemCount = child0 + child1;
}
}
// if no children returned finished items, then the sheet is
// either scrap or a finished item itself
if (item.ItemCount == 0)
{
if (baseShapes.ContainsKey(item.Size))
{
item.ItemCount = 1;
}
else
{
item.ItemCount = 0;
}
}
}
// add the item to the cache before we return it
shapeCache.Add(item.Size, item);
return item.ItemCount;
}
Finally, the general solution method uses a GCD function to rescale the dimensions to achieve scale-invariance. This is implemented in a static class called NaturalNumbers. I have included the rlevant parts of this class below:
static class NaturalNumbers
{
/// <summary>
/// Returns the Greatest Common Divisor of two natural numbers.
/// Returns Zero if either number is Zero,
/// Returns One if either number is One and both numbers are >Zero
/// </summary>
public static int GCD(int a, int b)
{
if ((a == 0) || (b == 0)) return 0;
if (a >= b)
return gcd_(a, b);
else
return gcd_(b, a);
}
/// <summary>
/// Returns the Greatest Common Divisor of a list of natural numbers.
/// (Note: will run fastest if the list is in ascending order)
/// </summary>
public static int GCD(IEnumerable<int> numbers)
{
// parameter checks
if (numbers == null || numbers.Count() == 0) return 0;
int first = numbers.First();
if (first <= 1) return 0;
int g = (int)first;
if (g <= 1) return g;
int i = 0;
foreach (int n in numbers)
{
if (i == 0)
g = n;
else
g = GCD(n, g);
if (g <= 1) return g;
i++;
}
return g;
}
// Euclidian method with Euclidian Division,
// From: https://en.wikipedia.org/wiki/Euclidean_algorithm
private static int gcd_(int a, int b)
{
while (b != 0)
{
int t = b;
b = (a % b);
a = t;
}
return a;
}
}
Please let me know of any problems or questions you might have with this solution.
Oops, forgot that I was also using this class:
public class SizeCount
{
public Vector2D Size;
public int ItemCount;
public SizeCount(Vector2D itemSize, int itemCount)
{
Size = itemSize;
ItemCount = itemCount;
}
}
As I mentioned in the comments, it would actually be pretty easy to factor this class out of the code, but it's still in there right now.

Understanding Big-O with a specific example

I am working on a rather simple question, to make sure that I understand these concepts.
The question is: there exists an array A of n elements, either being RED, WHITE, or BLUE. Rearrange the array such that all WHITE elements come before all BLUE elements, and all BLUE elements come before all RED elements. Construct an algorithm in O(n) time and O(1) space.
From my understanding, the pseudocode for the solution would be:
numW = numB = 0
for i = 0 to n:
if ARRAY[i] == WHITE:
numW++
else if ARRAY[i] == BLUE:
numB++
for i = 0 to n:
if numW > 0:
ARRAY[i] = WHITE
numW--
else if numB > 0:
ARRAY[i] = BLUE
numB--
else:
ARRAY[i] = RED
I believe it is O(n) because it runs through the loop twice and O(2n) is in O(n). I believe the space is O(1) because it is not dependent on the overall number of elements i.e. there will always be a count for each
Is my understanding correct?
If it's linear time, and your algorithm appears to be, then it's O(n) as you suspect. There's a great summary here: Big-O for Eight Year Olds?
Yes, your solution runs in O(n) time in O(1) space.
Below is my solution which also runs in O(n) time and O(1) space, but also works when we have references to objects, as #kenneth suggested in the comments.
import java.util.Arrays;
import java.util.Random;
import static java.lang.System.out;
class Color{
char c;
Color(char c){
this.c = c;
}
}
public class Solution {
private static void rearrangeColors(Color[] collection){
int ptr = 0;
// move all whites to the left
for(int i=0;i<collection.length;++i){
if(collection[i].c == 'W'){
swap(collection,ptr,i);
ptr++;
}
}
// move all blacks to the left after white
for(int i=ptr;i<collection.length;++i){
if(collection[i].c == 'B'){
swap(collection,ptr,i);
ptr++;
}
}
}
private static void swap(Color[] collection,int ptr1,int ptr2){
Color temp = collection[ptr1];
collection[ptr1] = collection[ptr2];
collection[ptr2] = temp;
}
private static void printColors(Color[] collection){
for(int i=0;i<collection.length;++i){
out.print(collection[i].c + ( i != collection.length - 1 ? "," : ""));
}
out.println();
}
public static void main(String[] args) {
// generate a random collection of 'Color' objects
Random r = new Random();
int array_length = r.nextInt(20) + 1;// to add 1 if in case 0 gets generated
Color[] collection = new Color[array_length];
char[] colors_domain = {'B','W','R'};
for(int i=0;i<collection.length;++i){
collection[i] = new Color(colors_domain[r.nextInt(3)]);
}
// print initial state
printColors(collection);
// rearrange them according to the criteria
rearrangeColors(collection);
// print final state
printColors(collection);
}
}
I won't say this is 100% correct, but a quick test case here did work. If anything, it shows the idea of being able to do it in one pass. Is it faster? Probably not. OP's answer I believe is still the best for this case.
#include <stdio.h>
char temp;
#define SWAP(a,b) { temp = a; a = b; b = temp;}
int main()
{
int n = 10;
char arr[] = "RWBRWBRWBR";
printf("%s\n", arr);
int white = 0;
for(int i=0; i<n; i++)
{
if(arr[i] == 'B')
{
SWAP(arr[i], arr[n-1]);
i--; n--;
}
else if(arr[i] == 'R')
{
SWAP(arr[i], arr[white]);
white++;
}
}
printf("%s\n", arr);
}

Points and segments

I'm doing online course and got stuck at this problem.
The first line contains two non-negative integers 1 ≤ n, m ≤ 50000 — the number of segments and points on a line, respectively. The next n lines contain two integers a_i ≤ b_i defining the i-th segment. The next line contain m integers defining points. All the integers are of absolute value at most 10^8. For each segment, output the number of points it is used from the n-points table.
My solution is :
for point in points:
occurrence = 0
for l, r in segments:
if l <= point <= r:
occurrence += 1
print(occurrence),
The complexity of this algorithm is O(m*n), which is obviously not very efficient. What is the best way of solving this problem? Any help will be appreciated!
Sample Input:
2 3
0 5
7 10
1 6 11
Sample Output:
1 0 0
Sample Input 2:
1 3
-10 10
-100 100 0
Sample Output 2:
0 0 1
You can use sweep line algorithm to solve this problem.
First, break each segment into two points, open and close points.
Add all these points together with those m points, and sort them based on their locations.
Iterating through the list of points, maintaining a counter, every time you encounter an open point, increase the counter, and if you encounter an end point, decrease it. If you encounter a point in list m point, the result for this point is the value of counter at this moment.
For example 2, we have:
1 3
-10 10
-100 100 0
After sorting, what we have is:
-100 -10 0 10 100
At point -100, we have `counter = 0`
At point -10, this is open point, we increase `counter = 1`
At point 0, so result is 1
At point 10, this is close point, we decrease `counter = 0`
At point 100, result is 0
So, result for point -100 is 0, point 100 is 0 and point 0 is 1 as expected.
Time complexity is O((n + m) log (n + m)).
[Original answer] by how many segments is each point used
I am not sure I got the problem correctly but looks like simple example of Histogram use ...
create counter array (one item per point)
set it to zero
process the last line incrementing each used point counter O(m)
write the answer by reading histogram O(n)
So the result should be O(m+n) something like (C++):
const int n=2,m=3;
const int p[n][2]={ {0,5},{7,10} };
const int s[m]={1,6,11};
int i,cnt[n];
for (i=0;i<n;i++) cnt[i]=0;
for (i=0;i<m;i++) if ((s[i]>=0)&&(s[i]<n)) cnt[s[i]]++;
for (i=0;i<n;i++) cout << cnt[i] << " "; // result: 0 1
But as you can see the p[] coordinates are never used so either I missed something in your problem description or you missing something or it is there just to trick solvers ...
[edit1] after clearing the inconsistencies in OP the result is a bit different
By how many points is each segment used:
create counter array (one item per segment)
set it to zero
process the last line incrementing each used point counter O(m)
write the answer by reading histogram O(m)
So the result is O(m) something like (C++):
const int n=2,m=3;
const int p[n][2]={ {0,5},{7,10} };
const int s[m]={1,6,11};
int i,cnt[m];
for (i=0;i<m;i++) cnt[i]=0;
for (i=0;i<m;i++) if ((s[i]>=0)&&(s[i]<n)) cnt[i]++;
for (i=0;i<m;i++) cout << cnt[i] << " "; // result: 1,0,0
[Notes]
After added new sample set to OP it is clear now that:
indexes starts from 0
the problem is how many points from table p[n] are really used by each segment (m numbers in output)
Use Binary Search.
Sort the line segments according to 1st value and the second value. If you use c++, you can use custom sort like this:
sort(a,a+n,fun); //a is your array of pair<int,int>, coordinates representing line
bool fun(pair<int,int> a, pair<int,int> b){
if(a.first<b.first)
return true;
if(a.first>b.first)
return false;
return a.second < b.second;
}
Then, for every point, find the 1st line that captures the point and the first line that does not (after the line that does of course). If no line captures the point, you can return -1 or something (and not check for the point that does not).
Something like:
int checkFirstHold(pair<int,int> a[], int p,int min, int max){ //p is the point
while(min < max){
int mid = (min + max)/2;
if(a[mid].first <= p && a[mid].second>=p && a[mid-1].first<p && a[mid-1].second<p) //ie, p is in line a[mid] and not in line a[mid-1]
return mid;
if(a[mid].first <= p && a[mid].second>=p && a[mid-1].first<=p && a[mid-1].second>=p) //ie, p is both in line a[mid] and not in line a[mid-1]
max = mid-1;
if(a[mid].first < p && a[mid].second<p ) //ie, p is not in line a[mid]
min = mid + 1;
}
return -1; //implying no point holds the line
}
Similarly, write a checkLastHold function.
Then, find checkLastHold - checkFirstHold for every point, which is the answer.
The complexity of this solution will be O(n log m), as it takes (log m) for every calculation.
Here is my counter-based solution in Java.
Note that all points, segment start and segment end are read into one array.
If points of different PointType have the same x-coordinate, then the point is sorted after segment start and before segment end. This is done to count the point as "in" the segment if it coincides with both the segment start (counter already increased) and the segment end (counter not yet decreased).
For storing an answer in the same order as the points from the input, I create the array result of size pointsCount (only points counted, not the segments) and set its element with index SuperPoint.index, which stores the position of the point in the original input.
import java.util.Arrays;
import java.util.Scanner;
public final class PointsAndSegmentsSolution {
enum PointType { // in order of sort, so that the point will be counted on both segment start and end coordinates
SEGMENT_START,
POINT,
SEGMENT_END,
}
static class SuperPoint {
final PointType type;
final int x;
final int index; // -1 (actually does not matter) for segments, index for points
public SuperPoint(final PointType type, final int x) {
this(type, x, -1);
}
public SuperPoint(final PointType type, final int x, final int index) {
this.type = type;
this.x = x;
this.index = index;
}
}
private static int[] countSegments(final SuperPoint[] allPoints, final int pointsCount) {
Arrays.sort(allPoints, (o1, o2) -> {
if (o1.x < o2.x)
return -1;
if (o1.x > o2.x)
return 1;
return Integer.compare( o1.type.ordinal(), o2.type.ordinal() ); // points with the same X coordinate by order in PointType enum
});
final int[] result = new int[pointsCount];
int counter = 0;
for (final SuperPoint superPoint : allPoints) {
switch (superPoint.type) {
case SEGMENT_START:
counter++;
break;
case SEGMENT_END:
counter--;
break;
case POINT:
result[superPoint.index] = counter;
break;
default:
throw new IllegalArgumentException( String.format("Unknown SuperPoint type: %s", superPoint.type) );
}
}
return result;
}
public static void main(final String[] args) {
final Scanner scanner = new Scanner(System.in);
final int segmentsCount = scanner.nextInt();
final int pointsCount = scanner.nextInt();
final SuperPoint[] allPoints = new SuperPoint[(segmentsCount * 2) + pointsCount];
int allPointsIndex = 0;
for (int i = 0; i < segmentsCount; i++) {
final int start = scanner.nextInt();
final int end = scanner.nextInt();
allPoints[allPointsIndex] = new SuperPoint(PointType.SEGMENT_START, start);
allPointsIndex++;
allPoints[allPointsIndex] = new SuperPoint(PointType.SEGMENT_END, end);
allPointsIndex++;
}
for (int i = 0; i < pointsCount; i++) {
final int x = scanner.nextInt();
allPoints[allPointsIndex] = new SuperPoint(PointType.POINT, x, i);
allPointsIndex++;
}
final int[] pointsSegmentsCounts = countSegments(allPoints, pointsCount);
for (final int count : pointsSegmentsCounts) {
System.out.print(count + " ");
}
}
}

Number flower pots in an arrangement

It's a Google interview question. There's a list of "T" and "F" only. All denotes a position such that T means position is occupied by a flower pot and F means pot is not there, so you can put another pot at this position. Find the number of pots that can be placed in a given arrangement such that no two pots are adjacent to each other(they can be adjacent in the given arrangement). If a position at the beginning is unoccupied then a pot can be placed if second position is also unoccupied and if the last position is unoccupied than a pot can be placed if second last position is also unoccupied. For ex.
TFFFTFFTFFFFT - returns 2
FFTTFFFFFTTFF - returns 4
I tried solving it by looking at adjacent values for every position with value F. Increased the counter if both adjacent positions were F and set this position as T. I need a better solution or any other solution(if any).
Let's analyse what has to be done.
So first we probably need to visit and examine each place. That suggests loop of some sort. E.g.:
for (int i = 0; i < myPlaces.Length; ++i)
When we are at a spot we have to check if it's occupied
if (place[i] == 'F')
but that's not enough to place the flower pot there. We have to check if the next and previous place is free
place[i-1]
place[i+1]
If all tree contain F you can put the flower pot there and move to next field
Now, we also have some exceptions from the rule. Beginning and end of the list. So you have to deal with them separately. E.g
if (i == 0)
{
// only check current position and next position
}
if (i == myPlaces.Length - 1) // minus 1 because indexing usually starts from 0
{
// only check current position and previous position
}
After that you can perform the checks mentioned previously.
Now let's think of the input data. Generally, it's a good habit not to modify the input data but make a copy and work on the copy. Also some data structures work better than the others for different tasks. Here you can use simple string to keep entry values. But I would say an array of chars would be a better option because then, when you find a place where you can put a flower pot you can actually replace the F with the T in an array. Then when you move to new spot your data structers knows that there is already a pot in the previous position so your algorithm won't put an adjacent one.
You would not be able to do that with string as strings are immutable and you would need to generate a new string each time.
Note that it's only a naive algorithm with a lot of scope for improvement and optimization. But my goal was rather to give some idea how to approach this kind of problems in general. I'll leave implementing of the details to you as an afternoon exercise before targeting a job at Google.
You may be able to do this with a modified Mergesort. Consider the flowerpots that can be placed in the singletons, then the flowerpots that can be placed in the doubleton merges of those singletons, up the tree to the full arrangement. It would complete in O(n lg n) for a list of n flowerpots.
There is certainly a way to do this with a modified Rod Cutting algorithm with complexity O(n^2). The subproblem is whether or not an open "false set" exists in the substring being considered. The "closed false sets" already have some maximum value computed for them. So, when a new character is added, it either increases the amount of flowerpots that can be inserted, or "locks in" the maximum quantity of available flowerpots for the substring.
Also, you know that the maximum flowerpots that can be placed in a set of n open positions bound by closed positions is n - 2 (else n-1 if only bracketed on one side, i.e. the string begins or ends with a "false set". The base condition (the first position is open, or the first position is closed) can calculated upon reaching the second flowerpot.
So, we can build up to the total number of flowerpots that can be inserted into the whole arrangement in terms of the maximum number of flowerpots that can be inserted into smaller subarrangements that have been previously calculated. By storing our previous calculations in an array, we reduce the amount of time necessary to calculate the maximum for the next subarrangement to a single array lookup and some constant-time calculations. This is the essence of dynamic programming!
EDIT: I updated the answer to provide a description of the Dynamic Programming approach. Please consider working through the interactive textbook I mentioned in the comments! http://interactivepython.org/runestone/static/pythonds/index.html
I would approach the problem like this. You need FFF to have one more pot, FFFFF for two pots, etc. To handle the end cases, add an F at each end.
Because this is very similar to a 16-bit integer, the algorithm should use tricks like binary arithmetic operations.
Here is an implementation in Python that uses bit masking (value & 1), bit shifting (value >>= 1) and math ((zeros - 1) / 2) to count empty slots and calculate how many flower pots could fit.
#value = 0b1000100100001
value = 0b0011000001100
width = 13
print bin(value)
pots = 0 # number of flower pots possible
zeros = 1 # number of zero bits in a row, start with one leading zero
for i in range(width):
if value & 1: # bit is one, count the number of zeros
if zeros > 0:
pots += (zeros - 1) / 2
zeros = 0
else: # bit is zero, increment the number found
zeros += 1
value >>= 1 # shift the bits to the right
zeros += 1 # add one trailing zero
pots += (zeros - 1) / 2
print pots, "flower pots"
The solution is really simple, check the previous and current value of the position and mark the position as plantable (or puttable) and increment the count. Read the next value, if it is already is planted, (backtrack and) change the previous value and decrement the count. The complexity is O(n). What we really want to check is the occurrence of 1001. Following is the implementation of the algorithm in Java.
public boolean canPlaceFlowers(List<Boolean> flowerbed, int numberToPlace) {
Boolean previous = false;
boolean puttable = false;
boolean prevChanged = false;
int planted = 0;
for (Boolean current : flowerbed) {
if (previous == false && current == false) {
puttable = true;
}
if (prevChanged == true && current == true) {
planted--;
}
if (puttable) {
previous = true;
prevChanged = true;
planted++;
puttable = false;
} else {
previous = current;
prevChanged = false;
}
}
if (planted >= numberToPlace) {
return true;
}
return false;
}
private static void canPlaceOneFlower(List<Boolean> flowerbed, FlowerBed fb) {
boolean result;
result = fb.canPlaceFlowers(flowerbed, 1);
System.out.println("Can place 1 flower");
if (result) {
System.out.println("-->Yes");
} else {
System.out.println("-->No");
}
}
private static void canPlaceTwoFlowers(List<Boolean> flowerbed, FlowerBed fb) {
boolean result;
result = fb.canPlaceFlowers(flowerbed, 2);
System.out.println("Can place 2 flowers");
if (result) {
System.out.println("-->Yes");
} else {
System.out.println("-->No");
}
}
private static void canPlaceThreeFlowers(List<Boolean> flowerbed, FlowerBed fb) {
boolean result;
result = fb.canPlaceFlowers(flowerbed, 3);
System.out.println("Can place 3 flowers");
if (result) {
System.out.println("-->Yes");
} else {
System.out.println("-->No");
}
}
private static void canPlaceFourFlowers(List<Boolean> flowerbed, FlowerBed fb) {
boolean result;
result = fb.canPlaceFlowers(flowerbed, 4);
System.out.println("Can place 4 flowers");
if (result) {
System.out.println("-->Yes");
} else {
System.out.println("-->No");
}
}
public static void main(String[] args) {
List<Boolean> flowerbed = makeBed(new int[] { 0, 0, 0, 0, 0, 0, 0 });
FlowerBed fb = new FlowerBed();
canPlaceFourFlowers(flowerbed, fb);
canPlaceThreeFlowers(flowerbed, fb);
flowerbed = makeBed(new int[] { 0, 0, 0, 1, 0, 0, 0 });
canPlaceFourFlowers(flowerbed, fb);
canPlaceThreeFlowers(flowerbed, fb);
canPlaceTwoFlowers(flowerbed, fb);
flowerbed = makeBed(new int[] { 1, 0, 0, 1, 0, 0, 0, 1 });
canPlaceFourFlowers(flowerbed, fb);
canPlaceThreeFlowers(flowerbed, fb);
canPlaceTwoFlowers(flowerbed, fb);
canPlaceOneFlower(flowerbed, fb);
}
My solution using dynamic programming.
ar is array in the form of ['F','T','F'].
import numpy as np
def pot(ar):
s = len(ar)
rt = np.zeros((s,s))
for k in range(0,s):
for i in range(s-k):
for j in range(i,i+k+1):
left = 0
right = 0
if ar[j] != 'F':
continue
if j-1 >= i and ar[j-1] == 'T':
continue
else:
left = 0
if j+1 <= i+k and ar[j+1] == 'T':
continue
else:
right = 0
if j-2 >= i:
left = rt[i][j-2]
if j+2 <= i+k:
right = rt[j+2][i+k]
rt[i][i+k] = max(rt[i][i+k], left+right+1)
return rt[0][len(ar)-1]
My solution written in C#
private static int CheckAvailableSlots(string str)
{
int counter = 0;
char[] chrs = str.ToCharArray();
if (chrs.FirstOrDefault().Equals('F'))
if (chrs.Length == 1)
counter++;
else if (chrs.Skip(1).FirstOrDefault().Equals('F'))
counter++;
if (chrs.LastOrDefault().Equals('F') && chrs.Reverse().Skip(1).FirstOrDefault().Equals('F'))
counter++;
for (int i = 1; i < chrs.Length - 2; i++)
{
if (chrs[i - 1].Equals('T'))
continue;
else if (chrs[i].Equals('F') && chrs[i + 1].Equals('F'))
{
chrs[i] = 'T';
counter++;
i++;
}
else
i++;
}
return counter;
}
// 1='T'
// 0='F'
int[] flowerbed = new int[] {1,0,0,0,0,1};
public boolean canPlaceFlowers(int[] flowerbed, int n) {
int tg = 0;
for (int i = 0, g = 1; i < flowerbed.length && tg < n; i++) {
g += flowerbed[i] == 0 ? flowerbed.length - 1 == i ? 2 : 1 : 0;
if (flowerbed[i] == 1 || i == flowerbed.length - 1) {
tg += g / 2 - (g % 2 == 0 ? 1 : 0);
g = 0;
}
}
return tg >= n;
}
Most of these answers (unless they alter the array or traverse and a copy) dont consider the situation where the first 3 (or last 3) pots are empty. These solutions will incorrectly determine that FFFT will contain 2 spaces, rather than just one. We therefore need to start at the third element (rather than then second) and end at index length - 3 (rather than length - 2). Also, while looping through the array, if an eligible index is found, the index just be incremented by 2, otherwise TTFFFFT would give 2 available plots instead of one. This is true unless you alter the array while looping or use a copy of the array and alter it.
Edit: this holds true unless the question is how many spaces are available for planting, rather than how many total plants can be added

Resources