目录
1. 有效括号序列(简单)
1.1. 题目描述
1.2 解题思路
方法一:栈
Java实现代码:
import java.util.*;
public class Solution {
public boolean isValid (String s) {
//辅助栈
Stack<Character> st = new Stack<Character>();
//遍历字符串
for(int i = 0; i < s.length(); i++){
//遇到左小括号
if(s.charAt(i) == '(')
//期待遇到右小括号
st.push(')');
//遇到左中括号
else if(s.charAt(i) == '[')
//期待遇到右中括号
st.push(']');
//遇到左打括号
else if(s.charAt(i) == '{')
//期待遇到右打括号
st.push('}');
//必须有左括号的情况下才能遇到右括号
else if(st.isEmpty() || st.pop() != s.charAt(i))
return false;
}
//栈中是否还有元素
return st.isEmpty();
}
}
方法二:哈希表 + 链表(性能提升)
class Solution {
import java.util.*;
public class Solution {
private static final Map<Character, Character> map = new HashMap<Character, Character>(){
{
put('{', '}'); put('[', ']'); put('(', ')'); put('?','?');
}};
public boolean isValid(String s) {
if(s.length() == 0)
return false;
if(s.length() % 2 == 1)
return false;
LinkedList<Character> stack = new LinkedList<Character>(){
{ add('?'); }};
for(char ch : s.toCharArray()){
if(map.containsKey(ch))
stack.addLast(ch);
else if(map.get(stack.removeLast()) != ch)
return false;
}
return stack.size() == 1;
}
}
}
2. 包含min函数的栈(简单)
2.1. 题目描述
2.2. 解题思路
方法:双栈法(推荐使用)
Java实现代码:
import java.util.Stack;
public class Solution {
//用于栈的push 与 pop
Stack<Integer> s1 = new Stack<Integer>();
//用于存储最小min
Stack<Integer> s2 = new Stack<Integer>();
public void push(int node) {
s1.push(node);
//空或者新元素较小,则入栈
if(s2.isEmpty() || s2.peek() > node)
s2.push(node);
else
//重复加入栈顶
s2.push(s2.peek());
}
public void pop() {
s1.pop();
s2.pop();
}
public int top() {
return s1.peek();
}
public int min() {
return s2.peek();
}
}
3. 字符串解码(中等)
3.1. 题目描述
3.2. 解题思路
方法一:栈操作
Java代码实现:
class Solution {
int ptr;
public String decodeString(String s) {
LinkedList<String> stk = new LinkedList<String>();
ptr = 0;
while (ptr < s.length()) {
char cur = s.charAt(ptr);
if (Character.isDigit(cur)) {
// 获取一个数字并进栈
String digits = getDigits(s);
stk.addLast(digits);
} else if (Character.isLetter(cur) || cur == '[') {
// 获取一个字母并进栈
stk.addLast(String.valueOf(s.charAt(ptr++)));
} else {
++ptr;
LinkedList<String> sub = new LinkedList<String>();
while (!"[".equals(stk.peekLast())) {
sub.addLast(stk.removeLast());
}
Collections.reverse(sub);
// 左括号出栈
stk.removeLast();
// 此时栈顶为当前 sub 对应的字符串应该出现的次数
int repTime = Integer.parseInt(stk.removeLast());
StringBuffer t = new StringBuffer();
String o = getString(sub);
// 构造字符串
while (repTime-- > 0) {
t.append(o);
}
// 将构造好的字符串入栈
stk.addLast(t.toString());
}
}
return getString(stk);
}
public String getDigits(String s) {
StringBuffer ret = new StringBuffer();
while (Character.isDigit(s.charAt(ptr))) {
ret.append(s.charAt(ptr++));
}
return ret.toString();
}
public String getString(LinkedList<String> v) {
StringBuffer ret = new StringBuffer();
for (String s : v) {
ret.append(s);
}
return ret.toString();
}
}
方法二:递归
Java代码实现:
class Solution {
String src;
int ptr;
public String decodeString(String s) {
src = s;
ptr = 0;
return getString();
}
public String getString() {
if (ptr == src.length() || src.charAt(ptr) == ']') {
// String -> EPS
return "";
}
char cur = src.charAt(ptr);
int repTime = 1;
String ret = "";
if (Character.isDigit(cur)) {
// String -> Digits [ String ] String
// 解析 Digits
repTime = getDigits();
// 过滤左括号
++ptr;
// 解析 String
String str = getString();
// 过滤右括号
++ptr;
// 构造字符串
while (repTime-- > 0) {
ret += str;
}
} else if (Character.isLetter(cur)) {
// String -> Char String
// 解析 Char
ret = String.valueOf(src.charAt(ptr++));
}
return ret + getString();
}
public int getDigits() {
int ret = 0;
while (ptr < src.length() && Character.isDigit(src.charAt(ptr))) {
ret = ret * 10 + src.charAt(ptr++) - '0';
}
return ret;
}
}
4. 每日温度(中等)
4.1. 题目描述
4.2. 解题思路
方法一:暴力
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
int length = temperatures.length;
int[] ans = new int[length];
int[] next = new int[101];
Arrays.fill(next, Integer.MAX_VALUE);
for (int i = length - 1; i >= 0; --i) {
int warmerIndex = Integer.MAX_VALUE;
for (int t = temperatures[i] + 1; t <= 100; ++t) {
if (next[t] < warmerIndex) {
warmerIndex = next[t];
}
}
if (warmerIndex < Integer.MAX_VALUE) {
ans[i] = warmerIndex - i;
}
next[temperatures[i]] = i;
}
return ans;
}
}
方法二:单调栈
class Solution {
public int[] dailyTemperatures(int[] temperatures) {
int length = temperatures.length;
int[] ans = new int[length];
Deque<Integer> stack = new LinkedList<Integer>();
for (int i = 0; i < length; i++) {
int temperature = temperatures[i];
while (!stack.isEmpty() && temperature > temperatures[stack.peek()]) {
int prevIndex = stack.pop();
ans[prevIndex] = i - prevIndex;
}
stack.push(i);
}
return ans;
}
}
5. 柱状图中最大的矩形(困难)
5.1. 题目描述
5.2. 解题思路
方法一:单调栈
class Solution {
public int largestRectangleArea(int[] heights) {
int n = heights.length;
int[] left = new int[n];
int[] right = new int[n];
Deque<Integer> mono_stack = new ArrayDeque<Integer>();
for (int i = 0; i < n; ++i) {
while (!mono_stack.isEmpty() && heights[mono_stack.peek()] >= heights[i]) {
mono_stack.pop();
}
left[i] = (mono_stack.isEmpty() ? -1 : mono_stack.peek());
mono_stack.push(i);
}
mono_stack.clear();
for (int i = n - 1; i >= 0; --i) {
while (!mono_stack.isEmpty() && heights[mono_stack.peek()] >= heights[i]) {
mono_stack.pop();
}
right[i] = (mono_stack.isEmpty() ? n : mono_stack.peek());
mono_stack.push(i);
}
int ans = 0;
for (int i = 0; i < n; ++i) {
ans = Math.max(ans, (right[i] - left[i] - 1) * heights[i]);
}
return ans;
}
}
方法二:单调栈 + 常数优化
class Solution {
public int largestRectangleArea(int[] heights) {
int n = heights.length;
int[] left = new int[n];
int[] right = new int[n];
Arrays.fill(right, n);
Deque<Integer> mono_stack = new ArrayDeque<Integer>();
for (int i = 0; i < n; ++i) {
while (!mono_stack.isEmpty() && heights[mono_stack.peek()] >= heights[i]) {
right[mono_stack.peek()] = i;
mono_stack.pop();
}
left[i] = (mono_stack.isEmpty() ? -1 : mono_stack.peek());
mono_stack.push(i);
}
int ans = 0;
for (int i = 0; i < n; ++i) {
ans = Math.max(ans, (right[i] - left[i] - 1) * heights[i]);
}
return ans;
}
}
6. 用两个栈实现队列一(简单)
6.1. 题目描述
6.2. 解题思路
方法一:双栈
class CQueue {
Deque<Integer> inStack;
Deque<Integer> outStack;
public CQueue() {
inStack = new ArrayDeque<Integer>();
outStack = new ArrayDeque<Integer>();
}
public void appendTail(int value) {
inStack.push(value);
}
public int deleteHead() {
if (outStack.isEmpty()) {
if (inStack.isEmpty()) {
return -1;
}
in2out();
}
return outStack.pop();
}
private void in2out() {
while (!inStack.isEmpty()) {
outStack.push(inStack.pop());
}
}
}
7. 用两个栈实现队列二(简单)
7.1. 题目描述
7.2. 解题思路
方法:双栈法(推荐使用)
Java实现代码:
import java.util.Stack;
public class Solution {
Stack<Integer> stack1 = new Stack<Integer>();
Stack<Integer> stack2 = new Stack<Integer>();
public void push(int node) {
stack1.push(node);
}
public int pop() {
//将第一个栈中内容弹出放入第二个栈中
while(!stack1.isEmpty())
stack2.push(stack1.pop());
//第二个栈栈顶就是最先进来的元素,即队首
int res = stack2.pop();
//再将第二个栈的元素放回第一个栈
while(!stack2.isEmpty())
stack1.push(stack2.pop());
return res;
}
}
8. 滑动窗口的最大值(困难)
8.1. 题目描述
8.2. 解题思路
方法:单调队列
Java代码实现:
class Solution {
public int[] maxAltitude(int[] heights, int limit) {
if(heights.length == 0 || limit == 0) return new int[0];
Deque<Integer> deque = new LinkedList<>();
int[] res = new int[heights.length - limit + 1];
for(int j = 0, i = 1 - limit; j < heights.length; i++, j++) {
// 删除 deque 中对应的 heights[i-1]
if(i > 0 && deque.peekFirst() == heights[i - 1])
deque.removeFirst();
// 保持 deque 递减
while(!deque.isEmpty() && deque.peekLast() < heights[j])
deque.removeLast();
deque.addLast(heights[j]);
// 记录窗口最大值
if(i >= 0)
res[i] = deque.peekFirst();
}
return res;
}
}
可以将 “未形成窗口” 和 “形成窗口后” 两个阶段拆分到两个循环里实现。
代码虽变长,但减少了冗余的判断操作。
class Solution {
public int[] maxAltitude(int[] heights, int limit) {
if(heights.length == 0 || limit == 0) return new int[0];
Deque<Integer> deque = new LinkedList<>();
int[] res = new int[heights.length - limit + 1];
// 未形成窗口
for(int i = 0; i < limit; i++) {
while(!deque.isEmpty() && deque.peekLast() < heights[i])
deque.removeLast();
deque.addLast(heights[i]);
}
res[0] = deque.peekFirst();
// 形成窗口后
for(int i = limit; i < heights.length; i++) {
if(deque.peekFirst() == heights[i - limit])
deque.removeFirst();
while(!deque.isEmpty() && deque.peekLast() < heights[i])
deque.removeLast();
deque.addLast(heights[i]);
res[i - limit + 1] = deque.peekFirst();
}
return res;
}
}
9. 滑动窗口的最大值(较难)
9.1. 题目描述
9.2. 解题思路
方法一:双向队列(推荐使用)
Java实现代码:
import java.util.*;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size) {
ArrayList<Integer> res = new ArrayList<Integer>();
//窗口大于数组长度的时候,返回空
if(size <= num.length && size != 0){
//双向队列
ArrayDeque <Integer> dq = new ArrayDeque<Integer>();
//先遍历一个窗口
for(int i = 0; i < size; i++){
//去掉比自己先进队列的小于自己的值
while(!dq.isEmpty() && num[dq.peekLast()] < num[i])
dq.pollLast();
dq.add(i);
}
//遍历后续数组元素
for(int i = size; i < num.length; i++){
//取窗口内的最大值
res.add(num[dq.peekFirst()]);
while(!dq.isEmpty() && dq.peekFirst() < (i - size + 1))
//弹出窗口移走后的值
dq.pollFirst();
//加入新的值前,去掉比自己先进队列的小于自己的值
while(!dq.isEmpty() && num[dq.peekLast()] < num[i])
dq.pollLast();
dq.add(i);
}
res.add(num[dq.pollFirst()]);
}
return res;
}
}
方法二:暴力法(扩展思路)
Java实现代码:
import java.util.*;
public class Solution {
public ArrayList<Integer> maxInWindows(int [] num, int size) {
ArrayList<Integer> res = new ArrayList<Integer>();
//窗口大于数组长度的时候,返回空
if(size <= num.length && size != 0)
//数组后面要空出窗口大小,避免越界
for(int i = 0; i <= num.length - size; i++){
//寻找每个窗口最大值
int max = 0;
for(int j = i; j < i + size; j++){
if(num[j] > max)
max = num[j];
}
res.add(max);
}
return res;
}
}
10. 队列的最大值(中等)
10.1. 题目描述
10.2. 解题思路
方法一:暴力
Java代码实现:
class Checkout {
int[] q = new int[20000];
int begin = 0, end = 0;
public Checkout() {
}
public int get_max() {
int ans = -1;
for (int i = begin; i != end; ++i) {
ans = Math.max(ans, q[i]);
}
return ans;
}
public void add(int value) {
q[end++] = value;
}
public int remove() {
if (begin == end) {
return -1;
}
return q[begin++];
}
}
方法二:维护一个单调的双端队列
class Checkout {
Queue<Integer> q;
Deque<Integer> d;
public Checkout() {
q = new LinkedList<Integer>();
d = new LinkedList<Integer>();
}
public int get_max() {
if (d.isEmpty()) {
return -1;
}
return d.peekFirst();
}
public void add(int value) {
while (!d.isEmpty() && d.peekLast() < value) {
d.pollLast();
}
d.offerLast(value);
q.offer(value);
}
public int remove() {
if (q.isEmpty()) {
return -1;
}
int ans = q.poll();
if (ans == d.peekFirst()) {
d.pollFirst();
}
return ans;
}
}
11.1. 题目描述
11.2. 解题思路
方法一:StringBuilder
class Solution {
public String removeStars(String s) {
StringBuilder rs = new StringBuilder();
// 遍历每个字符
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if (c == '*') {
// 尾部移除一位
rs.deleteCharAt(rs.length() - 1);
} else {
rs.append(c);
}
}
return rs.toString();
}
}
方法二:字符数组
class Solution {
public String removeStars(String s) {
int n = s.length();
char[] st = new char[n];
int head = -1;
for(int i = 0; i < n;i ++) {
char ch = s.charAt(i);
if(ch == '*') head --;
else st[++head] = ch;
}
return String.valueOf(st,0,head+1); //param: char arr, offset, count
}
}
12. 行星碰撞(中等)
12.1. 题目描述
12.2. 解题思路
方法一:栈模拟
class Solution {
public int[] asteroidCollision(int[] asteroids) {
Deque<Integer> stack = new ArrayDeque<Integer>();
for (int aster : asteroids) {
boolean alive = true;
while (alive && aster < 0 && !stack.isEmpty() && stack.peek() > 0) {
alive = stack.peek() < -aster; // aster 是否存在
if (stack.peek() <= -aster) { // 栈顶行星爆炸
stack.pop();
}
}
if (alive) {
stack.push(aster);
}
}
int size = stack.size();
int[] ans = new int[size];
for (int i = size - 1; i >= 0; i--) {
ans[i] = stack.pop();
}
return ans;
}
}
13. 最近的请求次数(简单)
13.1. 题目描述
13.2. 解题思路
方法一:队列
class RecentCounter {
Queue<Integer> q;
public RecentCounter() {
q = new LinkedList();
}
public int ping(int t) {
q.add(t);
while (q.peek() < t - 3000)
q.poll();
return q.size();
}
}
/**
* Your RecentCounter object will be instantiated and called as such:
* RecentCounter obj = new RecentCounter();
* int param_1 = obj.ping(t);
*/
14. Dota2 参议院(中等)
14.1. 题目描述
14.2 解题思路
方法一:贪心 + 「循环」队列
Java代码实现:
class Solution {
public String predictPartyVictory(String senate) {
int n = senate.length();
Queue<Integer> radiant = new LinkedList<Integer>();
Queue<Integer> dire = new LinkedList<Integer>();
for (int i = 0; i < n; ++i) {
if (senate.charAt(i) == 'R') {
radiant.offer(i);
} else {
dire.offer(i);
}
}
while (!radiant.isEmpty() && !dire.isEmpty()) {
int radiantIndex = radiant.poll(), direIndex = dire.poll();
if (radiantIndex < direIndex) {
radiant.offer(radiantIndex + n);
} else {
dire.offer(direIndex + n);
}
}
return !radiant.isEmpty() ? "Radiant" : "Dire";
}
}
15. 股票价格跨度(中等)
15.1. 题目描述
15.2. 解题思路
方法一:单调栈
class StockSpanner {
Deque<int[]> stack;
int idx;
public StockSpanner() {
stack = new ArrayDeque<int[]>();
stack.push(new int[]{-1, Integer.MAX_VALUE});
idx = -1;
}
public int next(int price) {
idx++;
while (price >= stack.peek()[1]) {
stack.pop();
}
int ret = idx - stack.peek()[0];
stack.push(new int[]{idx, price});
return ret;
}
}
16. 最小的K个数(中等)
16.1. 题目描述
16.2. 解题思路
方法一:堆排序(推荐使用)
Java实现代码:
import java.util.*;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> res = new ArrayList<Integer>();
//排除特殊情况
if(k == 0 || input.length == 0)
return res;
//大根堆
PriorityQueue<Integer> q = new PriorityQueue<>((o1, o2)->o2.compareTo(o1));
//构建一个k个大小的堆
for(int i = 0; i < k; i++)
q.offer(input[i]);
for(int i = k; i < input.length; i++){
//较小元素入堆
if(q.peek() > input[i]){
q.poll();
q.offer(input[i]);
}
}
//堆中元素取出入数组
for(int i = 0; i < k; i++)
res.add(q.poll());
return res;
}
}
方法二:sort排序法(扩展思路)
Java实现代码:
import java.util.*;
public class Solution {
public ArrayList<Integer> GetLeastNumbers_Solution(int [] input, int k) {
ArrayList<Integer> res = new ArrayList<Integer>();
//排除特殊情况
if(k == 0 || input.length == 0)
return res;
//排序
Arrays.sort(input);
//因为k<=input.length,取前k小
for(int i = 0; i < k; i++){
res.add(input[i]);
}
return res;
}
}
17. 寻找第K大(中等)
17.1. 题目描述
17.2. 解题思路
方法:快排+二分查找(推荐使用)
Java实现代码:
import java.util.*;
public class Solution {
//交换函数
Random r = new Random();
public static void swap(int arr[], int a, int b) {
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
public int partition(int[] a, int low, int high, int k){
//随机快排划分
int x = Math.abs(r.nextInt()) % (high - low + 1) + low;
swap(a, low, x);
int v = a[low];
int i = low + 1;
int j = high;
while(true){
//小于标杆的在右
while(j >= low + 1 && a[j] < v)
j--;
//大于标杆的在左
while(i <= high && a[i] > v)
i++;
if(i > j)
break;
swap(a, i, j);
i++;
j--;
}
swap(a, low, j);
//从0开始,所以为第j+1大
if(j + 1 == k)
return a[j];
//继续划分
else if(j + 1 < k)
return partition(a, j + 1, high, k);
else
return partition(a, low, j - 1, k);
}
public int findKth(int[] a, int n, int K) {
return partition(a, 0, n - 1, K);
}
}
18. 数据流中的中位数(中等)
18.1. 题目描述
18.2. 解题思路
方法一:插入排序法(推荐使用)
Java实现代码:
import java.util.*;
public class Solution {
private ArrayList<Integer> val = new ArrayList<Integer>();
public void Insert(Integer num) {
if(val.isEmpty())
//val中没有数据,直接加入
val.add(num);
//val中有数据,需要插入排序
else{
int i = 0;
//遍历找到插入点
for(; i < val.size(); i++){
if(num <= val.get(i))
break;
}
//插入相应位置
val.add(i, num);
}
}
public Double GetMedian() {
int n = val.size();
//奇数个数字
if(n % 2 == 1)
//类型转换
return (double)val.get(n / 2);
//偶数个数字
else{
double a = val.get(n / 2);
double b = val.get(n / 2 - 1);
return (a + b) / 2;
}
}
}
方法二:堆排序(扩展思路)
Java实现代码:
import java.util.*;
public class Solution {
//小顶堆,元素数值都比大顶堆大
private PriorityQueue<Integer> max = new PriorityQueue<>();
//大顶堆,元素数值较小
private PriorityQueue<Integer> min = new PriorityQueue<>((o1, o2)->o2.compareTo(o1));
//维护两个堆,取两个堆顶部即与中位数相关
public void Insert(Integer num) {
//先加入较小部分
min.offer(num);
//将较小部分的最大值取出,送入到较大部分
max.offer(min.poll());
//平衡两个堆的数量
if(min.size() < max.size())
min.offer(max.poll());
}
public Double GetMedian() {
//奇数个
if(min.size() > max.size())
return (double)min.peek();
else
//偶数个
return (double)(min.peek() + max.peek()) / 2;
}
}
19. 表达式求值(中等)
19.1. 题目描述
19.2. 解题思路
方法:栈 + 递归(推荐使用)
Java实现代码:
import java.util.*;
public class Solution {
public ArrayList<Integer> function(String s, int index){
Stack<Integer> stack = new Stack<Integer>();
int num = 0;
char op = '+';
int i;
for(i = index; i < s.length(); i++){
//数字转换成int数字
//判断是否为数字
if(s.charAt(i) >= '0' && s.charAt(i) <= '9'){
num = num * 10 + s.charAt(i) - '0';
if(i != s.length() - 1)
continue;
}
//碰到'('时,把整个括号内的当成一个数字处理
if(s.charAt(i) == '('){
//递归处理括号
ArrayList<Integer> res = function(s, i + 1);
num = res.get(0);
i = res.get(1);
if(i != s.length() - 1)
continue;
}
switch(op){
//加减号先入栈
case '+':
stack.push(num);
break;
case '-':
//相反数
stack.push(-num);
break;
//优先计算乘号
case '*':
int temp = stack.pop();
stack.push(temp * num);
break;
}
num = 0;
//右括号结束递归
if(s.charAt(i) == ')')
break;
else
op = s.charAt(i);
}
int sum = 0;
//栈中元素相加
while(!stack.isEmpty())
sum += stack.pop();
ArrayList<Integer> temp = new ArrayList<Integer>();
temp.add(sum);
temp.add(i);
return temp;
}
public int solve (String s) {
ArrayList<Integer> res = function(s, 0);
return res.get(0);
}
}
20. 不可能的出栈顺序(选填)
一个栈的入栈序列是a,b,c,d,e则出栈的不可能的输出序列是:C
- A:edcba
- B:decba
- C:dceab
- D:abcde
21. 逆波兰表达式求值(中等)
21.1. 题目描述
21.2 解题思路
方法一:栈
class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> stack = new LinkedList<Integer>();
int n = tokens.length;
for (int i = 0; i < n; i++) {
String token = tokens[i];
if (isNumber(token)) {
stack.push(Integer.parseInt(token));
} else {
int num2 = stack.pop();
int num1 = stack.pop();
switch (token) {
case "+":
stack.push(num1 + num2);
break;
case "-":
stack.push(num1 - num2);
break;
case "*":
stack.push(num1 * num2);
break;
case "/":
stack.push(num1 / num2);
break;
default:
}
}
}
return stack.pop();
}
public boolean isNumber(String token) {
return !("+".equals(token) || "-".equals(token) || "*".equals(token) || "/".equals(token));
}
}
方法二:数组模拟栈
class Solution {
public int evalRPN(String[] tokens) {
int n = tokens.length;
int[] stack = new int[(n + 1) / 2];
int index = -1;
for (int i = 0; i < n; i++) {
String token = tokens[i];
switch (token) {
case "+":
index--;
stack[index] += stack[index + 1];
break;
case "-":
index--;
stack[index] -= stack[index + 1];
break;
case "*":
index--;
stack[index] *= stack[index + 1];
break;
case "/":
index--;
stack[index] /= stack[index + 1];
break;
default:
index++;
stack[index] = Integer.parseInt(token);
}
}
return stack[index];
}
}
22. 有效的括号(简单)
22.1. 题目描述
22.2. 解题思路
方法一:栈
class Solution {
public boolean isValid(String s) {
int n = s.length();
if (n % 2 == 1) {
return false;
}
Map<Character, Character> pairs = new HashMap<Character, Character>() {
{
put(')', '(');
put(']', '[');
put('}', '{');
}};
Deque<Character> stack = new LinkedList<Character>();
for (int i = 0; i < n; i++) {
char ch = s.charAt(i);
if (pairs.containsKey(ch)) {
if (stack.isEmpty() || stack.peek() != pairs.get(ch)) {
return false;
}
stack.pop();
} else {
stack.push(ch);
}
}
return stack.isEmpty();
}
}
23. 最小栈(中等)
23.1. 题目描述
23.2. 解题思路
方法一:辅助栈
class MinStack {
Deque<Integer> xStack;
Deque<Integer> minStack;
public MinStack() {
xStack = new LinkedList<Integer>();
minStack = new LinkedList<Integer>();
minStack.push(Integer.MAX_VALUE);
}
public void push(int x) {
xStack.push(x);
minStack.push(Math.min(minStack.peek(), x));
}
public void pop() {
xStack.pop();
minStack.pop();
}
public int top() {
return xStack.peek();
}
public int getMin() {
return minStack.peek();
}
}
24. 用栈实现队列(简单)
24.1. 题目描述
24.2. 解题思路
方法一:双栈
class MyQueue {
Deque<Integer> inStack;
Deque<Integer> outStack;
public MyQueue() {
inStack = new ArrayDeque<Integer>();
outStack = new ArrayDeque<Integer>();
}
public void push(int x) {
inStack.push(x);
}
public int pop() {
if (outStack.isEmpty()) {
in2out();
}
return outStack.pop();
}
public int peek() {
if (outStack.isEmpty()) {
in2out();
}
return outStack.peek();
}
public boolean empty() {
return inStack.isEmpty() && outStack.isEmpty();
}
private void in2out() {
while (!inStack.isEmpty()) {
outStack.push(inStack.pop());
}
}
}
25. 用队列实现栈(简单)
25.1. 题目描述
25.2. 解题思路
方法一:两个队列
class MyStack {
Queue<Integer> queue1;
Queue<Integer> queue2;
/** Initialize your data structure here. */
public MyStack() {
queue1 = new LinkedList<Integer>();
queue2 = new LinkedList<Integer>();
}
/** Push element x onto stack. */
public void push(int x) {
queue2.offer(x);
while (!queue1.isEmpty()) {
queue2.offer(queue1.poll());
}
Queue<Integer> temp = queue1;
queue1 = queue2;
queue2 = temp;
}
/** Removes the element on top of the stack and returns that element. */
public int pop() {
return queue1.poll();
}
/** Get the top element. */
public int top() {
return queue1.peek();
}
/** Returns whether the stack is empty. */
public boolean empty() {
return queue1.isEmpty();
}
}
方法二:一个队列
class MyStack {
Queue<Integer> queue;
/** Initialize your data structure here. */
public MyStack() {
queue = new LinkedList<Integer>();
}
/** Push element x onto stack. */
public void push(int x) {
int n = queue.size();
queue.offer(x);
for (int i = 0; i < n; i++) {
queue.offer(queue.poll());
}
}
/** Removes the element on top of the stack and returns that element. */
public int pop() {
return queue.poll();
}
/** Get the top element. */
public int top() {
return queue.peek();
}
/** Returns whether the stack is empty. */
public boolean empty() {
return queue.isEmpty();
}
}