锁定老帖子 主题:百度一面算法题(常数时间内求栈中最大值)
精华帖 (0) :: 良好帖 (3) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2011-11-04
tswwz 写道 可以考虑与当前stack维护对应的代表stack对应位置的最大值的栈MaxStack
对于栈stack push元素 valueA时 maxValue = popMaxStack(); pushMaxStack(maxValue); if (valueA >= maxValue) pushStack(valueA) ; pushMaxStack(valueA); if (valueA < maxValue) pushStack(valueA) ; pushMaxStack(maxValue); pop元素 maxValue = popMaxStack(); pushMaxStack(maxValue); valueA = popStack(); popMaxStack(); 这样取最大值时,直接 maxValue = popMaxStack();pushMaxStack(maxValue);就ok了。 我的作法是popStack()的元素valueA与popMaxStack()的元素maxValue得比较一下. 若相等(表明弹出的元素是当前最大的那个元素),则不做任何操作; 若不相等(表明弹出的元素不是当前最大的那个元素),则再做pushMaxStack(maxValue)操作. |
|
返回顶楼 | |
发表时间:2011-11-04
yeshaoting 写道
算法描述: 一个栈stack,具有push和pop操作,其时间复杂度皆为O(1)。 设计算法max操作,求栈中的最大值,该操作的时间复杂度也要求为O(1)。 可以修改栈的存储方式,push,pop的操作,但是要保证O(1)的时间复杂度,空间时间复杂度无要求。 思路: 我借助一个变量count和一个数组空间(其实就是一个栈)完成该时间复杂度为O(1)的算法设计。
这里面不需要用到快排吧。。那样的话还能叫o(1)? 贴上我的code:用了个最大栈保存添加路径上的最大值,删除的时候如果相等撤销最大值栈中的顶部元素即可。
另鄙视下,共享东西的时候都鼓掌叫好,求助发问就隐藏哦鄙视哦扣分哦臭鸡蛋烂白菜都来了。。。不多说了 果断以后文章只丢博客里
package sunfa; import java.util.Arrays; import java.util.Comparator; import java.util.LinkedList; import java.util.Random; public class LinkedListMaxVal<E> { public static void main(String[] args) { LinkedListMaxVal<Integer> stack = new LinkedListMaxVal<Integer>( new Comparator<Integer>() { public int compare(Integer o1, Integer o2) { return o1 - o2; } }); Random ran = new Random(); for (int i = 1; i <= 20; i++) { stack.push(ran.nextInt(100)); System.out.println(stack + "," + stack.max()+","+stack.maxStack); if (i % 4 == 0) { Integer ee = stack.peek(); System.out.println("=============>pop:"+ee+"," + stack + "," + stack.max()+","+stack.maxStack); stack.pop(); } } System.out.println("pop all>>>>>>>>>>>>>------------------"); System.out.println("删除的元素 | 数据栈 | 最大值 | 最大值栈"); while(!stack.isEmpty()){ Integer ee = stack.peek(); System.out.println("pop:" +ee+","+ stack + "," + stack.max()+","+stack.maxStack); stack.pop(); } System.out.println("---end-----"); System.out.println(stack); } private Object[] item; private int count;//栈内元素数目 ,栈顶元素索引为count-1 private LinkedList<E> maxStack = new LinkedList<E>();//最大值备用栈,为省事借用链表 private final String EMPTY_STACK_STR = "空栈"; private Comparator<E> comp; public LinkedListMaxVal(Comparator<E> c) { item = new Object[10]; comp = c; } public void push(E e) { if (e == null) throw new NullPointerException(); if (count + 1 == item.length) item = Arrays.copyOf(item, item.length << 1); item[count++] = e; if (count == 1) maxStack.push(e); else { if (compare(maxStack.peekFirst(), e) <= 0)//=号不要丢了,这很关键 maxStack.push(e); } } public E pop() { if (isEmpty()) throw new NullPointerException(EMPTY_STACK_STR); E e = peek(); item[count - 1] = null; if (count == 1) maxStack.pop(); else { if (compare(maxStack.peekFirst(), e) == 0) maxStack.pop(); } count--; return e; } public E max() { if (maxStack.isEmpty()) throw new NullPointerException(EMPTY_STACK_STR); return maxStack.peekFirst(); } public E peek() { if (isEmpty()) throw new NullPointerException(EMPTY_STACK_STR); return (E) item[count - 1]; } private int compare(E e1, E e2) { return comp != null ? (((comp).compare(e1, e2))) : (((Comparable<E>) e1).compareTo(e2)); } public boolean isEmpty() { return count == 0; } public String toString() { String s = "["; for (int i = 0; i < item.length; i++) { if (item[i] != null) s += item[i] + ","; } if (s.length() == 1) { s += "]"; } else { s = s.substring(0, s.length() - 1) + "]"; } return s; } } |
|
返回顶楼 | |
发表时间:2011-11-05
543089122 写道
yeshaoting 写道
算法描述: 一个栈stack,具有push和pop操作,其时间复杂度皆为O(1)。 设计算法max操作,求栈中的最大值,该操作的时间复杂度也要求为O(1)。 可以修改栈的存储方式,push,pop的操作,但是要保证O(1)的时间复杂度,空间时间复杂度无要求。 思路: 我借助一个变量count和一个数组空间(其实就是一个栈)完成该时间复杂度为O(1)的算法设计。
这里面不需要用到快排吧。。那样的话还能叫o(1)? 贴上我的code:用了个最大栈保存添加路径上的最大值,删除的时候如果相等撤销最大值栈中的顶部元素即可。
是不需要用到快排. 之前贴上代码的仁兄,是用快排求栈中所有数据的中间值.对于求最大值和最小值跟你的过程是一样的.
思路和代码写得挺好的.投你一票了. |
|
返回顶楼 | |
发表时间:2011-11-05
yeshaoting 写道 tswwz 写道 可以考虑与当前stack维护对应的代表stack对应位置的最大值的栈MaxStack
对于栈stack push元素 valueA时 maxValue = popMaxStack(); pushMaxStack(maxValue); if (valueA >= maxValue) pushStack(valueA) ; pushMaxStack(valueA); if (valueA < maxValue) pushStack(valueA) ; pushMaxStack(maxValue); pop元素 maxValue = popMaxStack(); pushMaxStack(maxValue); valueA = popStack(); popMaxStack(); 这样取最大值时,直接 maxValue = popMaxStack();pushMaxStack(maxValue);就ok了。 确实是有额外用到一个栈空间. 我的push元素想法跟你一样. 但是没太看懂你的pop元素. 其实就是出栈。。。。 popStack();popMaxStack(); maxValue = popMaxStack(); pushMaxStack(maxValue); 这个只是说明取最大值的方法,没啥意义,估计误导人了。 |
|
返回顶楼 | |
发表时间:2011-11-06
yeshaoting 写道
543089122 写道
yeshaoting 写道
算法描述: 一个栈stack,具有push和pop操作,其时间复杂度皆为O(1)。 设计算法max操作,求栈中的最大值,该操作的时间复杂度也要求为O(1)。 可以修改栈的存储方式,push,pop的操作,但是要保证O(1)的时间复杂度,空间时间复杂度无要求。 思路: 我借助一个变量count和一个数组空间(其实就是一个栈)完成该时间复杂度为O(1)的算法设计。
这里面不需要用到快排吧。。那样的话还能叫o(1)? 贴上我的code:用了个最大栈保存添加路径上的最大值,删除的时候如果相等撤销最大值栈中的顶部元素即可。
是不需要用到快排. 之前贴上代码的仁兄,是用快排求栈中所有数据的中间值.对于求最大值和最小值跟你的过程是一样的.
思路和代码写得挺好的.投你一票了.
|
|
返回顶楼 | |
发表时间:2011-11-07
没咋看明白。栈顶上压一个代表max的值不行么?一弹弹出俩,按需修改,压回俩。也算O(1) 吧
|
|
返回顶楼 | |
发表时间:2011-11-08
EldonReturn 写道 没咋看明白。栈顶上压一个代表max的值不行么?一弹弹出俩,按需修改,压回俩。也算O(1) 吧
这样是不行的. 倘若即将弹出的那个值等于当前max的值当如何??? |
|
返回顶楼 | |
发表时间:2011-11-08
yeshaoting 写道 YuHuang.Neil 写道 我的实现是
import java.util.ArrayList; import java.util.EmptyStackException; import java.lang.NullPointerException; public class StackForPriorImpl<E extends Comparable<E>> implements IStackForPrior<E> { private int numberOfObject; private ArrayList<E> dataForOrginal; private ArrayList<E> dataForMaximun; private ArrayList<E> dataForMinimun; private E maxElement; private E minElement; public StackForPriorImpl(){ this.numberOfObject = 0; this.dataForOrginal = new ArrayList<E>(); this.dataForMaximun = new ArrayList<E>(); this.dataForMinimun = new ArrayList<E>(); } @Override public void push(E e) { if(e==null){ throw new NullPointerException(); } dataForOrginal.add(e); if(numberOfObject==0){ maxElement = e; minElement = e; this.dataForMaximun.add(maxElement); this.dataForMinimun.add(minElement); }else{ if(e.compareTo(maxElement)>0){ dataForMaximun.add(e); maxElement = e; }else{ dataForMaximun.add(maxElement); } if(e.compareTo(minElement)<0){ dataForMinimun.add(e); minElement = e; }else{ dataForMinimun.add(minElement); } } ++numberOfObject; } @Override public E pop() { if(numberOfObject==0) { throw new EmptyStackException(); } int index = --numberOfObject; dataForMaximun.remove(index); maxElement = dataForMaximun.get(index-1); dataForMinimun.remove(index); minElement = dataForMinimun.get(index-1); E e = dataForOrginal.get(index); dataForOrginal.remove(index); return e; } @Override public E peekMedian() { if(numberOfObject==0){ throw new EmptyStackException(); } Object[] elementArray=this.dataForOrginal.toArray(); int lengthOfElementArray = elementArray.length; quickSort(elementArray,0,lengthOfElementArray-1); return (E)elementArray[lengthOfElementArray/2]; } @Override public E peekMaximum() { if(numberOfObject==0){ throw new EmptyStackException(); } int index = numberOfObject - 1; return this.dataForMaximun.get(index); } @Override public E peekMinimum() { if(numberOfObject==0) { throw new EmptyStackException(); } int index = numberOfObject - 1; return this.dataForMinimun.get(index); } @Override public int size() { return this.numberOfObject; } private static <E> void quickSort(E[] elementArray,int low,int high){ if(low<high){ int q = partition(elementArray,low,high); quickSort(elementArray,low,q-1); quickSort(elementArray,q+1,high); } } private static <E> int partition(E[] elementArray,int low,int high){ int i = low, j=high+1; E e= elementArray[low]; while(true){ while(elementArray[++i].toString().compareTo(e.toString())<0 && i<high); while(elementArray[--j].toString().compareTo(e.toString())>0); if(i>=j) break; E temp = elementArray[i]; elementArray[i]=elementArray[j]; elementArray[j]=temp; } elementArray[low] = elementArray[j]; elementArray[j]=e; return j; } public static void main(String[] args){ StackForPriorImpl<Integer> stack=new StackForPriorImpl<Integer>(); stack.push(new Integer(2)); stack.push(new Integer(1)); stack.push(new Integer(2)); stack.push(new Integer(2)); stack.push(new Integer(6)); stack.push(new Integer(4)); stack.push(new Integer(2)); stack.push(new Integer(5)); System.out.println("size = "+stack.size()); System.out.println("peekMaximun = "+stack.peekMaximum().toString()); System.out.println("peekMinimun = "+stack.peekMinimum().toString()); System.out.println("peekMedian = "+stack.peekMedian().toString()); } } 写得很好~~ 跟我当时的做法是一样的. 好扯,找个代码你pop掉一个以后在看结果,还是6... |
|
返回顶楼 | |
发表时间:2011-11-08
lzyzizi 写道 yeshaoting 写道 YuHuang.Neil 写道 我的实现是
import java.util.ArrayList; import java.util.EmptyStackException; import java.lang.NullPointerException; public class StackForPriorImpl<E extends Comparable<E>> implements IStackForPrior<E> { private int numberOfObject; private ArrayList<E> dataForOrginal; private ArrayList<E> dataForMaximun; private ArrayList<E> dataForMinimun; private E maxElement; private E minElement; public StackForPriorImpl(){ this.numberOfObject = 0; this.dataForOrginal = new ArrayList<E>(); this.dataForMaximun = new ArrayList<E>(); this.dataForMinimun = new ArrayList<E>(); } @Override public void push(E e) { if(e==null){ throw new NullPointerException(); } dataForOrginal.add(e); if(numberOfObject==0){ maxElement = e; minElement = e; this.dataForMaximun.add(maxElement); this.dataForMinimun.add(minElement); }else{ if(e.compareTo(maxElement)>0){ dataForMaximun.add(e); maxElement = e; }else{ dataForMaximun.add(maxElement); } if(e.compareTo(minElement)<0){ dataForMinimun.add(e); minElement = e; }else{ dataForMinimun.add(minElement); } } ++numberOfObject; } @Override public E pop() { if(numberOfObject==0) { throw new EmptyStackException(); } int index = --numberOfObject; dataForMaximun.remove(index); maxElement = dataForMaximun.get(index-1); dataForMinimun.remove(index); minElement = dataForMinimun.get(index-1); E e = dataForOrginal.get(index); dataForOrginal.remove(index); return e; } @Override public E peekMedian() { if(numberOfObject==0){ throw new EmptyStackException(); } Object[] elementArray=this.dataForOrginal.toArray(); int lengthOfElementArray = elementArray.length; quickSort(elementArray,0,lengthOfElementArray-1); return (E)elementArray[lengthOfElementArray/2]; } @Override public E peekMaximum() { if(numberOfObject==0){ throw new EmptyStackException(); } int index = numberOfObject - 1; return this.dataForMaximun.get(index); } @Override public E peekMinimum() { if(numberOfObject==0) { throw new EmptyStackException(); } int index = numberOfObject - 1; return this.dataForMinimun.get(index); } @Override public int size() { return this.numberOfObject; } private static <E> void quickSort(E[] elementArray,int low,int high){ if(low<high){ int q = partition(elementArray,low,high); quickSort(elementArray,low,q-1); quickSort(elementArray,q+1,high); } } private static <E> int partition(E[] elementArray,int low,int high){ int i = low, j=high+1; E e= elementArray[low]; while(true){ while(elementArray[++i].toString().compareTo(e.toString())<0 && i<high); while(elementArray[--j].toString().compareTo(e.toString())>0); if(i>=j) break; E temp = elementArray[i]; elementArray[i]=elementArray[j]; elementArray[j]=temp; } elementArray[low] = elementArray[j]; elementArray[j]=e; return j; } public static void main(String[] args){ StackForPriorImpl<Integer> stack=new StackForPriorImpl<Integer>(); stack.push(new Integer(2)); stack.push(new Integer(1)); stack.push(new Integer(2)); stack.push(new Integer(2)); stack.push(new Integer(6)); stack.push(new Integer(4)); stack.push(new Integer(2)); stack.push(new Integer(5)); System.out.println("size = "+stack.size()); System.out.println("peekMaximun = "+stack.peekMaximum().toString()); System.out.println("peekMinimun = "+stack.peekMinimum().toString()); System.out.println("peekMedian = "+stack.peekMedian().toString()); } } 写得很好~~ 跟我当时的做法是一样的. 好扯,找个代码你pop掉一个以后在看结果,还是6... 没太看懂的意思.... 这个程序我觉得写得没有问题呀. 期待你的高见. |
|
返回顶楼 | |
发表时间:2011-11-08
做一链状列表;
push的时候 链表插入元素,并保持链表降序排列; pup的时候直接在链表种找到结点删除即可。 链表第一个结点始终为栈中元素最大值。 |
|
返回顶楼 | |