03链表+栈+队列(D4_综合刷题)

目录

1. 有效括号序列(简单)

1.1. 题目描述

1.2 解题思路

方法一:栈

方法二:哈希表 + 链表(性能提升)

2. 包含min函数的栈(简单)

2.1. 题目描述

2.2. 解题思路

方法:双栈法(推荐使用)

3. 字符串解码(中等)

3.1. 题目描述

3.2. 解题思路

方法一:栈操作

方法二:递归

4. 每日温度(中等)

4.1. 题目描述

4.2. 解题思路

方法一:暴力

方法二:单调栈

5. 柱状图中最大的矩形(困难)

5.1. 题目描述

5.2. 解题思路

方法一:单调栈

方法二:单调栈 + 常数优化

6. 用两个栈实现队列一(简单)

6.1. 题目描述

6.2. 解题思路

方法一:双栈

7. 用两个栈实现队列二(简单)

7.1. 题目描述

7.2. 解题思路

方法:双栈法(推荐使用)

8. 滑动窗口的最大值(困难)

8.1. 题目描述

8.2. 解题思路

方法:单调队列

9. 滑动窗口的最大值(较难)

9.1. 题目描述

9.2. 解题思路

方法一:双向队列(推荐使用)

方法二:暴力法(扩展思路)

10. 队列的最大值(中等)

10.1. 题目描述

10.2. 解题思路

方法一:暴力

方法二:维护一个单调的双端队列

11.1. 题目描述

11.2. 解题思路

方法一:StringBuilder

方法二:字符数组

12. 行星碰撞(中等)

12.1. 题目描述

12.2. 解题思路

方法一:栈模拟

13. 最近的请求次数(简单)

13.1. 题目描述

13.2. 解题思路

方法一:队列

14. Dota2 参议院(中等)

14.1. 题目描述

14.2 解题思路

方法一:贪心 + 「循环」队列

15. 股票价格跨度(中等)

15.1. 题目描述

15.2. 解题思路

方法一:单调栈

16. 最小的K个数(中等)

16.1. 题目描述

16.2. 解题思路

方法一:堆排序(推荐使用)

方法二:sort排序法(扩展思路)

17. 寻找第K大(中等)

17.1. 题目描述

17.2. 解题思路

方法:快排+二分查找(推荐使用)

18. 数据流中的中位数(中等)

18.1. 题目描述

18.2. 解题思路

方法一:插入排序法(推荐使用)

方法二:堆排序(扩展思路)

19. 表达式求值(中等)

19.1. 题目描述

19.2. 解题思路

方法:栈 + 递归(推荐使用)

20. 不可能的出栈顺序(选填)

21. 逆波兰表达式求值(中等)

21.1. 题目描述

21.2 解题思路

方法一:栈

方法二:数组模拟栈

22. 有效的括号(简单)

22.1. 题目描述

22.2. 解题思路

方法一:栈

23. 最小栈(中等)

23.1. 题目描述

23.2. 解题思路

方法一:辅助栈

24. 用栈实现队列(简单)

24.1. 题目描述

24.2. 解题思路

方法一:双栈

25. 用队列实现栈(简单)

25.1. 题目描述

25.2. 解题思路

方法一:两个队列

方法二:一个队列


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();
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CodingW丨编程之路

你的鼓励是我创作最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值