Amazon Interview Question
Software Engineer / DevelopersThis of it this way:
You have two pointers. One pointer moves two times, while the other moves once. When the first point hits the end, where is the first one?
O(n) time. Unfold the stack recursively, calculate the index of the middle, then fold it back and return the middle.
template <class T>
pair<T, size_t> middle(stack<T> s, size_t i){
if (s.empty())
if (i == 0) throw "empty stack!";
else
return make_pair<T, size_t>(T(), i / 2);
T tmp = s.top();
s.pop();
pair<T, size_t> res = middle(s, i + 1);
s.push(tmp);
if (i == res.second) res.first = tmp; // found the middle!
return res;
}
well yes, it should be
return make_pair(T(), i / 2);
or
return pair<T, size_t>(T(), i / 2);
use two stacks.
space complexity will be doubled but push,pop,top,mid all will be O(1).
Idea is to push the element twice in second stack, so that the second stack will get filled twice as fast as first one so it'll always contain mid element on top for current available elements in stack one.
Below is the pseudo code:
Let S1 and S2 are two stacks and curMid=0
PUSH:
{
S1.Push(data);
if(S1.size() > S2.size())
{
if(S2.size()==0)curMid=data;
S2.Push(curMid);
S2.Push(curMid);
curMid=S1.top();
}
}
POP:
{
data=S1.Pop();
if(S1.size()+1 < S2.size())
{
S2.Pop();
S2.Pop();
}
return data;
}
MID:
{
return S2.top();
}
what is the point if you already know the size of stack ??
you can always calculate size/2..
@above: but u cant access element at position size/2 in stack. stack gives u only push, pop and top operation. If size operation is not allowed then u can maintain a count for size.
I think Approach is correct but the pseudo code given is not correct for push operation.
@Above: It depends on what the interviewer actually excepts us to know. If other than push,pop and top are allowed we can use stack.elementAt(stack.size/2) ( in JAVA)
I actually don't understand how pushing to one of the stacks twice would work. Maybe you can elaborate a little bit?
This was posted earlier in question?id=10274826 (which I suppose is the same question).
T MiddleElement<T>(Stack<T> s) {
if (s.IsEmpty()) throw;
queue <T> candidates;
T current;
while(!s.IsEmpty()) {
candidates.Enqueue(s.Pop());
if (!s.IsEmpty()) {
candidates.Enqueue(s.Pop());
}
current = candidates.Dequeue();
}
return current;
}
Pop the stack and store the element into a binary search tree, the root should be the middle value.
You can not achieve this by simply popping the elements from stack and storing it in BST .
For example :- 1,4,3,5,22,55,9 here if u will start from 1 then i will be the root element which is not the middle value .
Idea is to apply merge sort on Stack and then find the (keep track of size of stack while merging ) then calculate mid of the stack it will give you the correct value .
Complexity will be o(n log n) .
If any one have a good solution as compare to this then please share it .
Hi,
How about the following approach.
lets take stack is stack1.
lets take 2 pointers , p1 and p2
for every pop , keep increment p1 , so that p1 will point to latest pop'ed out element.
increment p2 for every odd count of pop's...
increment p2 , for 1 , 3 , 5 , pop'ings etc..
so at the end , p2 will point to middle element of the stack.
The idea is to get the middle element in O(1) T.C.
We maintain a Doubly Linked List as the under lying
data structure for storage. We maintain a pointer
to the middle element as the linked list grows or shrinks
public class MiddleStack{
private DLLNode headNode;
private DLLNode middleNode;
private int middleIndex;
private int size;
public MiddleStack(){
this.headNode = new DLLNode(null);
}
public void push(Object data){
if(headNode == null){ //empty stack
headNode = new DLLNode(data);
middleNode = headNode;
}else if(headNode.getData() == null){ //empty stack
headNode.setData(data);
middleNode = headNode;
}else{
DLLNode llNode = new DLLNode(data);
llNode.setNext(headNode);
headNode.setPrevious(llNode);
headNode = llNode;
}
size++;
if(size == 1){
middleIndex = 1;
} else if (middleIndex < Math.round((double)size/ 2.0 )){
middleIndex++;
middleNode = middleNode.getPrevious();
}
}
public Object top(){
if(headNode == null || headNode.getData() == null){
return null;
}else{
return headNode.getData();
}
}
public Object pop(){
if(headNode == null || headNode.getData() == null){
throw new EmptyStackException("Stack empty");
}else{
Object data = headNode.getData();
if(headNode.getNext() == null){
headNode.setData(null);
}else{
headNode = headNode.getNext();
}
headNode.setPrevious(null);
size--;
if(size == 1){
middleIndex = 1;
} else if (middleIndex > Math.round((double)size/ 2.0 )){
middleIndex--;
middleNode = middleNode.getNext();
}
return data;
}
}
public Object getMiddle(){
return middleNode.getData();
}
public static void main(String[] args){
MiddleStack middleStack = new MiddleStack();
middleStack.push(1);
middleStack.push(2);
middleStack.push(3);
middleStack.push(4);
middleStack.push(5);
middleStack.push(6);
middleStack.push(7);
middleStack.push(8);
middleStack.push(9);
middleStack.push(10);
while(!middleStack.isEmpty()){
System.out.println("Top: " + middleStack.top() + " ---> Middle: " + middleStack.getMiddle());
middleStack.pop();
}
}
}
The output of the main method is as follows.
Top: 10 ---> Middle: 5
Top: 9 ---> Middle: 5
Top: 8 ---> Middle: 4
Top: 7 ---> Middle: 4
Top: 6 ---> Middle: 3
Top: 5 ---> Middle: 3
Top: 4 ---> Middle: 2
Top: 3 ---> Middle: 2
Top: 2 ---> Middle: 1
Top: 1 ---> Middle: 1
This solution is not valid. It's not allowed to modify the stack structure. You can only assume 3 of the operations are available - push, pop, top.
And above all, you misunderstood the problem! It asks for middle value, not middle index. It's better to pay attention to question first.
I guess you should read the output properly...its not the middle index...that's printed above....its the middle value. The question never said...don't modify the underlying implementation in stack...we need to come out with a quick way to get middle value. I guess you should think properly before passing meaningless comments.
Well, the output seems confusing because of the silly input that you used in your program as it was simply a sorted dataset.
Now, when I look at your code, it seems buggy altogether. Let me know what you get for stack with below items:
7 <top>
4
10
8
2
6
15
Median is 7. And one suggestion, rather than posting your big code (even NOT aligned) here, upload ur code on ideone.com, and post the link here. It'd be easy for others to run ur solution, and finding erroneous output.
why all are telling the middle of the stack by index.........tell the middle of the stack by value....
like sorting the stack and then returning the middle element of sorted stack
give more efficient algorithm for this
Let us consider stack as S, and take two stacks S1 and S2. Pop from S and push into S1 and S2 alternatively and make count of elements say COUNT. If COUNT is even then you can take any of two stacks S1,S2(because middle of stack contains two elements) and send it to the same function iteratively. If COUNT is odd, take second stack S2 and send to the same function iteratively. Do this until you get COUNT = 1 in S2.
I am a little confused... Is the question about the middle index value of the stack or the median of the stack? I am assuming its the middle value(median)
Eg:
Elements of Stack:
2
7
4
5
1
8
6
5
3
Here middle indexed value is 1 ( index 4)
Where as median is 4
Please let me know if I misunderstood the problem??
If it is middle value, then we can do the following
1. Pop all the elements of the stack and sum them and divide my the number of elements, in the above example 2+7+4+5+1+8+6+5+3= 42 => 42/9 => 4
2. Push all the elements back to the stack and while pushing store the value nearest to your calculated median.
3. Return the index and median of the stack.
If it is middle value, then we can do the following
1. Pop all the elements of the stack and sum them and divide my the number of elements, in the above example 2+7+4+5+1+8+6+5+3= 42 => 42/9 => 4
2. Push all the elements back to the stack and while pushing store the value nearest to your calculated median.
3. Return the index and median of the stack.
i have a doubt on this, 1. without sorting how can we get the median? 2. you said "nearest to your calculated median", does it means lower neatest or upper nearest? In your example, nearest to 4 becomes 3 and 5. which one i need to take?
I think it is not the right solution. please clarify if i am wrong.
sort the stack using two temporary stacks(not constraint on space, we can do with one temporary stack) and i counted the no of elements in the stack. At the end of first outer loop, i can able to get the sorted stack in s1 and i have no of elements "count". While popping back, using "count", i can able to get the middle value(median). If the "count" is even (mid1+mid2)/2 becomes the median, otherwise mid2
becomes the median.
clarify me if there are any errors.
int returnMidVal(stack s)
{
int count=0,val=0,val1=0;
stack s1, s2;
while(s!=null)
{
val = s.pop();
count++;
while(s1!=null)
{
val1 = s1.pop();
if(val >= val1)
{
s1.push(val1);
break;
}
else
{
s2.push(val1);
}
}
s1.push(val);
while(s2!=null)
{
s1.push(s2.pop());
}
}
if(count == 0) return 0;
int mid1, mid2;
int index = 0;
while(s1!=null)
{
val = s1.pop();
index++;
if(index == (count/2)) mid1 = val;
if(index == (count/2)+1) mid2 = val;
s.push(val);
}
if(count%2 ==0)
{
return (mid1+mid2)/2;
}
else
{
return mid2;
}
}
Following algo can be used to find the middle value
1. pop all the elements of the stack into an array ( you will get the num of elements in the stack)
2. Apply quick sort partition algo on th array, by selecting a random pivot
- using the pivot index we can determine if the median lies left of the pivot or in the right
- select an appropriate half and apply the partion algo, until we find the pivot that is the center of the array
3. Return that element or the median of medians
If we can destroy the stack:
Pop the elements into a queue. Pop into queue twice, dequeue once. One pass.
- Anonymous August 19, 2011