给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
思路:
用队列来存放滑动窗口里边的元素的下标,对队列有一下操作:
(1)队列的头元素是这个队列中最大的元素。
(2)每次放队列中存放元素之前都要判断,如果不比队尾元素小,删除队尾元素,再存放。
(3)要判断何时存放队头元素至结果集中,以及何时删除队头元素。
/**
* 滑动窗口的最大值
* @param num
* @param size
* @return
*/
public static ArrayList<Integer> maxInWindows(int[] num, int size) {
ArrayList<Integer> result = new ArrayList<>();
if(num.length == 0 || num.length < size || size <= 0)
return result;
LinkedList<Integer> qmax = new LinkedList<>();
for(int i = 0; i < num.length; i++) {
while(!qmax.isEmpty() && num[qmax.peekLast()] <= num[i])
qmax.pollLast();
qmax.add(i);
if(qmax.getFirst() == i - size)
qmax.pollFirst();
if(i >= size - 1)
result.add(num[qmax.getFirst()]);
}
return result;
}
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
思路:太简单,就不说了。
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
while(!stack2.empty())
stack1.push(stack2.pop());
stack1.push(node);
}
public int pop() {
while(!stack1.empty())
stack2.push(stack1.pop());
return stack2.pop();
}
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
这道题也很简单,主要是实现min函数查找栈中的最小元素,且时间复杂度为1。对空间没有要求,所以可以借助额外空间。
思路:
定义两个栈,dataStack
和minStack
,dataStack
用来保存数据,minStack
用来存放最小数。
每次使用push函数存放数据的时候,首先将数据放在dataStack
中,然后再判断minStack
栈顶元素是否小于或者等于当前要存放的数据,如果不是,则将数据存放minStack
,如果是,则将minStack
的栈顶元素再次存放道minStack
中,确保dataStack
和minStack
的相同高度。
Stack<Integer> dataStack = new Stack<>();
Stack<Integer> minStack = new Stack<>();
public void push(int node) {
dataStack.push(node);
if(minStack.empty() || minStack.peek() >= node) {
minStack.push(node);
}else {
minStack.push(minStack.peek());
}
}
public void pop() {
dataStack.pop();
minStack.pop();
}
public int top() {
return dataStack.peek();
}
public int min() {
return minStack.peek();
}
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
思路:
借用一个辅助栈,将压入序列逐一压入栈,每压入一个元素,都用栈顶元素与弹出序列从头比较,如果不相等则继续压入,如果相等,删除栈顶元素,弹出序列向后移动一位,再继续比较……
当整个程序结束,如果栈中还有元素,则该弹出序列不是这个栈的弹出序列,反之则是。
/**
* 栈的压入、弹出序列
* @param pushA
* @param popA
* @return
*/
public boolean IsPopOrder(int[] pushA, int[] popA) {
Stack<Integer> stack = new Stack<>();
for(int i = 0, j = 0; i < pushA.length; i++) {
stack.push(pushA[i]);
while(!stack.empty() && stack.peek() == popA[j]) {
stack.pop();
j++;
}
}
return stack.empty();
}