理论
第一章 刷题
232. 用栈实现队列
准备两个栈push和pop:用户给我的数永远进push栈、用户要的数据永远从pop拿;
如果有数据进来,则压入push栈
如果拿数据,看pop栈有没有,如果有,直接pop;如果没有,看push栈有没有;没有报错;有则让push栈数据全部进入pop栈,再返回栈顶。
倒这个行为有两个限制:1.如果push的数据要向pop栈倒,则必须一次性倒完;如果pop栈有东西,push栈一定不能倒。
class MyQueue {Stack<Integer> push;Stack<Integer> pop;/** Initialize your data structure here. */public MyQueue() {push = new Stack<Integer>();pop = new Stack<Integer>();}/** Push element x to the back of queue. */public void push(int x) {push.push(x);}/** Removes the element from in front of queue and returns that element. */public int pop() {this.dao();if (pop.isEmpty()) {throw new RuntimeException("no data");}return pop.pop();}/** Get the front element. */public int peek() {this.dao();if (pop.isEmpty()) {throw new RuntimeException("no data");}return pop.peek();}/** Returns whether the queue is empty. */public boolean empty() {this.dao();return pop.isEmpty();}private void dao() {if (!pop.isEmpty()) {return;}while (!push.isEmpty()) {pop.push(push.pop());}}}/*** Your MyQueue object will be instantiated and called as such:* MyQueue obj = new MyQueue();* obj.push(x);* int param_2 = obj.pop();* int param_3 = obj.peek();* boolean param_4 = obj.empty();*/
225. 用队列实现栈
其实实现起来很傻:无非就是如何放数据和如何取数据!
准备两个队列a和b
有数据放入,则放入队列a;取数据时,将队列a中数据放入b,要留一个弹出;再取还是如此
数永远保存在data队列,只有出或者peek操作时,才到help队列,然后又立刻索引变换过来。
就是这么简单:
class MyStack {private Queue<Integer> data;private Queue<Integer> help;/** Initialize your data structure here. */public MyStack() {data = new LinkedList<Integer>();help = new LinkedList<Integer>();}/** Push element x onto stack. */public void push(int x) {data.offer(x);}/** Removes the element on top of the stack and returns that element. */public int pop() {if (data.isEmpty()) {throw new RuntimeException("no data");}while (data.size() != 1) {help.offer(data.poll());}swap();return help.poll();}/** Get the top element. */public int top() {if (data.isEmpty()) {throw new RuntimeException("no data");}while (data.size() != 1) {help.offer(data.poll());}swap();int num = help.poll();data.offer(num);return num;}/** Returns whether the stack is empty. */public boolean empty() {return data.isEmpty();}private void swap() {Queue<Integer> temp = data;data = help;help = temp;}}/*** Your MyStack object will be instantiated and called as such:* MyStack obj = new MyStack();* obj.push(x);* int param_2 = obj.pop();* int param_3 = obj.top();* boolean param_4 = obj.empty();*/
20. 有效的括号
系统中处处都是栈的应用!
由于栈结构的特殊性,非常适合做对称匹配类的题目。
class Solution {public boolean isValid(String s) {Stack<Character> stack = new Stack<Character>();for (int i = 0; i < s.length(); i++) {char ch = s.charAt(i);if (stack.isEmpty() || ch == '(' || ch == '{' || ch == '[') {stack.push(ch);} else {char left = stack.peek();if ((left == '(' && ch == ')') || (left == '[' && ch == ']') || (left == '{' && ch == '}')) {stack.pop();} else {return false;}}}return stack.isEmpty();}}
1047. 删除字符串中的所有相邻重复项
匹配问题都是栈的强项!
如果想不到栈,就很难办了!
实话说,官网代码比我写的好的多,我的就不贴了!
class Solution {public String removeDuplicates(String S) {StringBuffer stack = new StringBuffer();int top = -1;for (int i = 0; i < S.length(); ++i) {char ch = S.charAt(i);if (top >= 0 && stack.charAt(top) == ch) {stack.deleteCharAt(top);--top;} else {stack.append(ch);++top;}}return stack.toString();}}
150. 逆波兰表达式求值
有没有想过计算机是如何处理表达式的?
其实看到题目九知道怎么解了。
这里大家思考一下,怎么将一个我们可以看懂的式子转化成逆波兰表达法才是难点!
class Solution {
public int evalRPN(String[] tokens) {
Stack<String> stack = new Stack<String>();
for (int i = 0; i < tokens.length; i++) {
if (tokens[i].equals("+") || tokens[i].equals("-") || tokens[i].equals("*") || tokens[i].equals("/")) {
stack.push(calculate(Integer.valueOf(stack.pop()), Integer.valueOf(stack.pop()), tokens[i]) + "");
} else {
stack.push(tokens[i]);
}
}
return Integer.valueOf(stack.pop());
}
private int calculate(int num2, int num1, String flag) {
if (flag.equals("+")) {
return num1 + num2;
} else if (flag.equals("-")) {
return num1 - num2;
} else if (flag.equals("*")) {
return num1 * num2;
} else {
return num1 / num2;
}
}
}
239. 滑动窗口最大值
class Solution {
public int[] maxSlidingWindow(int[] nums, int k) {
if (nums == null || nums.length < k) {
return null;
}
int[] res = new int[nums.length - k + 1];
int index = 0;
LinkedList<Integer> qmax = new LinkedList<Integer>();
for (int i = 0; i < nums.length; i++) {
while (!qmax.isEmpty() && nums[qmax.peekLast()] <= nums[i]) {
qmax.pollLast();
}
qmax.addLast(i);
if (qmax.peekFirst() == i - k) {
qmax.pollFirst();
}
if (i >= k - 1) {
res[index++] = nums[qmax.peekFirst()];
}
}
return res;
}
}
347. 前 K 个高频元素

class Solution {
public int[] topKFrequent(int[] nums, int k) {
Map<Integer, Integer> occurrences = new HashMap<Integer, Integer>();
for (int num : nums) {
occurrences.put(num, occurrences.getOrDefault(num, 0) + 1);
}
// int[] 的第一个元素代表数组的值,第二个元素代表了该值出现的次数
PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {
public int compare(int[] m, int[] n) {
return m[1] - n[1];
}
});
for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {
int num = entry.getKey(), count = entry.getValue();
if (queue.size() == k) {
if (queue.peek()[1] < count) {
queue.poll();
queue.offer(new int[]{num, count});
}
} else {
queue.offer(new int[]{num, count});
}
}
int[] ret = new int[k];
for (int i = 0; i < k; i++) {
ret[i] = queue.poll()[0];
}
return ret;
}
}



