LeetCode 刷题汇总之栈

前言

本文隶属于专栏《LeetCode 刷题汇总》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构请见LeetCode 刷题汇总

正文

20. 有效的括号

看到括号,第一反应一定是栈

Java 和 Scala 版本的栈推荐都使用 ArrayDeque,其中 Scala 也可以使用 ListBuffer,不过 ArrayDeque 的 API 更友好一点

Java 版本

class Solution {
    public boolean isValid(String s) {
        ArrayDeque<Character> stack = new ArrayDeque<>();
        for (char c : s.toCharArray()) {
            if (c == '(')
                stack.push(')');
            else if (c == '{')
                stack.push('}');
            else if (c == '[')
                stack.push(']');
            else if (stack.isEmpty() || stack.pop() != c)
                return false;
        }
        return stack.isEmpty();
    }
}

Scala 版本

import java.util.ArrayDeque

object Solution {
  def isValid(s: String): Boolean = {
    val stack = new ArrayDeque[Char]()
    for (c <- s) {
      c match {
        case '(' => stack.push(')')
        case '[' => stack.push(']')
        case '{' => stack.push('}')
        case _ => if (stack.isEmpty || stack.pop() != c) return false
      }
    }
    stack.isEmpty
  }
}

42. 接雨水

接雨水这道题的思路:暴力解法( O(n^2) )-> 动态规划 3 次遍历( O(n) )-> 单调栈 1 次遍历( O(n) )-> 双指针 1 次遍历 ( O(n) )

选择单调栈是因为遍历过程中满足单调性(栈底到栈顶递减)
接雨水中的凹槽口也很容易想到数学函数中的极小值,进而想到单调性 -> 单调栈

Java 版本

class Solution {
    public int trap(int[] height) {
        int n = height.length, res = 0;
        ArrayDeque<Integer> stack = new ArrayDeque<>();
        for(int i = 0; i < n; i++){
            while(!stack.isEmpty() && height[i] > height[stack.peek()]){
                // 出栈操作发生在凹槽口的底点,即由递减到递增的转折点,当然这里只是方便理解,后续可能需要计算出不同高度的雨水量
                int top = stack.pop();
                if(stack.isEmpty()){
                    break;
                }
                int left = stack.peek();
                // 这里推荐使用特值法来推断
                int width = i - left - 1;
                // 对于凹槽口的底点来说,左右的较小值减去当前点的高度,即为雨水的高度
                int h = Math.min(height[i], height[left]) - height[top];
                res += width * h;
            }
            stack.push(i);
        }
        return res;
    }
}

Scala 版本

import java.util.ArrayDeque

import scala.util.control.Breaks._

object Solution {
  def trap(height: Array[Int]): Int = {
    if (height == null || height.isEmpty) return 0
    val stack = new ArrayDeque[Int]()
    var top, distance, boundedHeight, ans = 0
    for (current <- height.indices) {
      breakable(
        while (!stack.isEmpty && height(current) > height(stack.peek)) {
          top = stack.pop()
          if (stack.isEmpty) break
          distance = current - stack.peek() - 1
          boundedHeight = math.min(height(current), height(stack.peek())) - height(top)
          ans += distance * boundedHeight
        }
      )
      stack.push(current)
    }
    ans
  }
}

71. 简化路径

借助栈结构,然后在遍历的过程中对单点和双点特殊处理下

Java 版本

import java.util.StringJoiner;
class Solution {
    public String simplifyPath(String path) {
        String[] paths = path.split("/");
        ArrayDeque<String> stack = new ArrayDeque<>();
        for(String p: paths){
            if(!p.isEmpty() && !p.equals(".")){
                if(p.equals("..") && !stack.isEmpty()){
                    stack.pop();
                }else if(!p.equals("..")){
                    stack.push(p);
                }
            }
        }
        StringJoiner sj = new StringJoiner("/");
        // 这里我们借助 ArrayList 来逆序栈
        List<String> res = new ArrayList<>(stack);
        Collections.reverse(res);
        for(String s: res){
            sj.add(s);
        }
        return "/" + sj;
    }
}

Scala 版本

import scala.collection.mutable.ListBuffer

object Solution {
  def simplifyPath(path: String): String = {
    val paths = path.split("/")
    val res = ListBuffer[String]()
    for (p <- paths if p.nonEmpty && !p.equals(".")) {
      if (p.equals("..") && res.nonEmpty) res.remove(res.size - 1)
      else if (!p.equals("..")) res += p
    }
    "/" + res.mkString("/")
  }
}

这里使用 ListBuffer 代码更简洁

84. 柱状图中最大的矩形

class Solution {
    public int largestRectangleArea(int[] heights) {
        int len = heights.length;
        ArrayDeque<Integer> s = new ArrayDeque<>();
        int maxArea = 0;
        for (int i = 0; i <= len; i++){
            int h = (i == len ? 0 : heights[i]);
            if (s.isEmpty() || h >= heights[s.peek()]) {
                s.push(i);
            } else {
                maxArea = Math.max(maxArea, heights[s.pop()] * (s.isEmpty() ? i : i - 1 - s.peek()));
                i--;
            }
        }
        return maxArea;
    }
}
import java.util.ArrayDeque

object Solution {
  def largestRectangleArea(heights: Array[Int]): Int = {
    //保存遍历过程中执行到每一步比当前高度小的数组下标
    val stack = new ArrayDeque[Int]()
    stack.push(-1)
    var max: Int = 0
    for (i <- heights.indices) {
      while (stack.peek != -1 && heights(stack.peek) >= heights(i))
        max = Math.max(max, heights(stack.pop) * (i - stack.peek - 1))
      stack.push(i)
    }
    while (stack.peek != -1)
      max = Math.max(max, heights(stack.pop) * (heights.length - stack.peek - 1))
    max
  }
}

85. 最大矩形

这一题和 84 题其实是一样的,只需要在遍历每一行的时候,把包含 1 的列当前柱形图的柱形就好了。
同时需要注意,遍历到每一行柱形图的形状是不一样的,但都是以当前遍历到的行为 X 轴,纵方向为 Y 轴,连续的 1 高度可以叠加。

class Solution {
    public int maximalRectangle(char[][] matrix) {
        if(matrix.length == 0) return 0;
        int n = matrix[0].length;
        // 数组用来统计每一列中 1 的数目,即柱形图的高度
        int[] heights = new int[n];
        int max = 0;
        for(char[] row : matrix){
            for(int i = 0; i < n; i++){
                if(row[i] == '1'){
                    heights[i] += 1;
                } else {
                    heights[i] = 0;
                }
            }
            // 和 84 题一样,通过栈来计算遍历到当前行柱形图中最大的矩形
            max = Math.max(max, maxArea(heights));
        }
        return max;
    }

    public int maxArea(int[] heights){
        ArrayDeque<Integer> stack = new ArrayDeque();
        int max = 0;
        for(int i = 0; i <= heights.length; i++){
            int h = (i == heights.length) ? 0 : heights[i];
            while(!stack.isEmpty() && heights[stack.peek()] > h){
                int index = stack.pop();
                int left = -1;
                if(!stack.isEmpty()){
                    left =  stack.peek();
                }
                max = Math.max(max, heights[index] * (i - left - 1));
            }
            stack.push(i);
        }
        return max;
    }
}
import java.util.ArrayDeque

object Solution {
  def maximalRectangle(matrix: Array[Array[Char]]): Int = {
    if (matrix.length == 0) return 0
    val n = matrix(0).length
    // 数组用来统计每一列中 1 的数目,即柱形图的高度
    val heights = new Array[Int](n)
    var max = 0
    for (row <- matrix) {
      for (i <- 0 until n) {
        if (row(i) == '1') heights(i) += 1
        else heights(i) = 0
      }
      // 和 84 题一样,通过栈来计算遍历到当前行柱形图中最大的矩形
      max = Math.max(max, maxArea(heights))
    }
    max
  }

  def maxArea(heights: Array[Int]): Int = {
    val stack = new ArrayDeque[Int]()
    var max = 0
    for (i <- 0 to heights.length) {
      val h = if (i == heights.length) 0
      else heights(i)
      while (!stack.isEmpty && heights(stack.peek) > h) {
        val index = stack.pop
        var left = -1
        if (!stack.isEmpty) left = stack.peek
        max = Math.max(max, heights(index) * (i - left - 1))
      }
      stack.push(i)
    }
    max
  }
}

94. 二叉树的中序遍历

二叉树的几种遍历方式都可以用栈来实现
要掌握递归和迭代两种实现方式,这里建议记忆

递归

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        helper(root, list);
        return list;
    }

    private void helper(TreeNode node, List<Integer> list){
        if(node == null){
            return;
        }
        helper(node.left, list);
        list.add(node.val);
        helper(node.right, list);
    }
}

迭代

下面的解法建议记忆

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<Integer> inorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        Stack<TreeNode> stack = new Stack<>();
        while(root != null || !stack.isEmpty()){
            while(root != null){
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            list.add(root.val);
            root = root.right;
        }
        return list;
    }
}
/**
 * Definition for a binary tree node.
 * class TreeNode(_value: Int = 0, _left: TreeNode = null, _right: TreeNode = null) {
 *   var value: Int = _value
 *   var left: TreeNode = _left
 *   var right: TreeNode = _right
 * }
 */
import java.util.ArrayDeque
import scala.collection.mutable.ListBuffer
object Solution {
    def inorderTraversal(root: TreeNode): List[Int] = {
        val list = ListBuffer[Int]()
        val stack = new ArrayDeque[TreeNode]()
        var node = root
        while(node != null || !stack.isEmpty){
            while(node != null){
                stack.push(node)
                node = node.left
            }
            node = stack.pop
            list += node.value
            node = node.right
        }
        list.toList
    }
}

103. 二叉树的锯齿形层序遍历

递归

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */
class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> list = new ArrayList<>();
        helper(list, root, 0);
        return list;
    }

    private void helper(List<List<Integer>> list, TreeNode node, int level){
        if(node == null) return;
        addList(list, node, level);
        helper(list, node.left, level + 1);
        helper(list, node.right, level + 1);
    }

    private void addList(List<List<Integer>> list, TreeNode node, int level){
        List<Integer> cur;
        if(list.size() > level) cur = list.get(level);
        else{
            cur = new ArrayList<>();
            list.add(cur);
        }
        if(level % 2 == 1) cur.add(0, node.val);
        else cur.add(node.val);
    }
}
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> list = new ArrayList<>();
        helper(list, root, 0);
        return list;
    }

    private void helper(List<List<Integer>> list, TreeNode node, int level){
        if(node == null){
            return;
        }
        if(level < list.size()){
            if(level % 2 == 0){
                ((LinkedList)list.get(level)).addLast(node.val);
            }else{
                ((LinkedList)list.get(level)).addFirst(node.val);
            }
        }else{
            LinkedList<Integer> tmp = new LinkedList<>();
            tmp.add(node.val);
            list.add(tmp);
        }
        helper(list, node.left, level + 1);
        helper(list, node.right, level + 1);
    }
}

迭代

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        List<List<Integer>> ret = new ArrayList<>();
        if(root==null){
            return ret;
        }
        Deque<TreeNode> queue = new ArrayDeque<>();
        Deque<TreeNode> stack = new ArrayDeque<>();

        queue.add(root);
        int level =1;///层数为奇数时,正常顺序遍历,层数为偶数,倒序遍历
        while (!queue.isEmpty()||!stack.isEmpty()){

            boolean isOrder = (level&1)==1;
            int n =isOrder?queue.size():stack.size();
            List<Integer> sub = new ArrayList<>();
            for(int i=0;i<n;i++){


                if(isOrder){
                    TreeNode curNode = queue.poll();
                    sub.add(curNode.val);
                    if(curNode.left!=null){
                        stack.push(curNode.left);
                    }
                    if(curNode.right!=null){
                        stack.push(curNode.right);
                    }
                }else{
                    TreeNode curNode = stack.poll();
                    sub.add(curNode.val);
                    if(curNode.right!=null){
                        queue.addFirst(curNode.right);
                    }
                    if(curNode.left!=null){
                        queue.addFirst(curNode.left);
                    }

                }
            }
            level++;
            ret.add(sub);
        }
        return ret;
    }
}
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<List<Integer>> zigzagLevelOrder(TreeNode root) {
        if(root==null) return Collections.emptyList();
        List<List<Integer>> result=new ArrayList<>();
        Queue<TreeNode> queue=new LinkedList<>();
        queue.offer(root);
        
        int level=1;
        while(!queue.isEmpty()){
            int queueSize=queue.size();
            List<Integer> childList=new ArrayList<>();
            Stack<Integer> stack=new Stack<>();
            for(int i=0;i<queueSize;i++){
                TreeNode currNode=queue.poll();
                if(currNode!=null){
                    if(level%2==0) stack.add(currNode.val);
                    else childList.add(currNode.val);
                    if(currNode.left!=null) queue.add(currNode.left);
                    if(currNode.right!=null) queue.add(currNode.right);
                }
            }
            while(!stack.isEmpty()){
                childList.add(stack.pop());
            }
            result.add(childList);
            level++;
        }
        
        return result;
    }
}

144. 二叉树的前序遍历

递归

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        helper(list, root);
        return list;
    }

    private void helper(List<Integer> list, TreeNode node){
        if(node == null){
            return;
        }
        list.add(node.val);
        helper(list, node.left);
        helper(list, node.right);
    }
}

迭代

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> preorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        if (root == null) {
            return res;
        }
        ArrayDeque<TreeNode> stack = new ArrayDeque<>();
        TreeNode node = root;
        while (!stack.isEmpty() || node != null) {
            while (node != null) {
                res.add(node.val);
                stack.push(node);
                node = node.left;
            }
            node = stack.pop();
            node = node.right;
        }
        return res;
    }
}

145. 二叉树的后序遍历

递归

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> res = new ArrayList<>();
        helper(res, root);
        return res;
    }

    private void helper(List<Integer> list, TreeNode node){
        if(node == null){
            return;
        }
        helper(list, node.left);
        helper(list, node.right);
        list.add(node.val);
    }
}

迭代

迭代版本的后序遍历与前面最大的不同点在于有一个 prev 指针

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode() {}
 *     TreeNode(int val) { this.val = val; }
 *     TreeNode(int val, TreeNode left, TreeNode right) {
 *         this.val = val;
 *         this.left = left;
 *         this.right = right;
 *     }
 * }
 */
class Solution {
    public List<Integer> postorderTraversal(TreeNode root) {
        List<Integer> list = new ArrayList<>();
        if(root == null){
            return list;
        }
        ArrayDeque<TreeNode> stack = new ArrayDeque<>();
        TreeNode prev = null;
        while(root != null || !stack.isEmpty()){
            while(root != null){
                stack.push(root);
                root = root.left;
            }
            root = stack.pop();
            if(root.right == null || root.right == prev){
                list.add(root.val);
                prev = root;
                root = null;
            }else{
                stack.push(root);
                root = root.right;
            }
        }
        return list;
    }
}

150. 逆波兰表达式求值

class Solution {
    public int evalRPN(String[] tokens) {
        Deque<Integer> stack = new LinkedList<>();
        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 static int evalRPN(String[] tokens) {
		int[] numStack = new int[tokens.length / 2 + 1];
		int index = 0;
		for (String s : tokens) {
			switch (s) {
			case "+":
				numStack[index - 2] += numStack[--index];
				break;
			case "-":
				numStack[index - 2] -= numStack[--index];
				break;
			case "*":
				numStack[index - 2] *= numStack[--index];
				break;
			case "/":
				numStack[index - 2] /= numStack[--index];
				break;
			default:
				// numStack[index++] = Integer.valueOf(s);
				//valueOf改为parseInt,减少自动拆箱装箱操作
				numStack[index++] = Integer.parseInt(s);
				break;
			}
		}
		return numStack[0];
	}
}

155. 最小栈

class MinStack {
    Deque<Integer> xStack;
    Deque<Integer> minStack;

    public MinStack() {
        xStack = new LinkedList<>();
        minStack = new LinkedList<>();
        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();
    }
}

/**
 * Your MinStack object will be instantiated and called as such:
 * MinStack obj = new MinStack();
 * obj.push(x);
 * obj.pop();
 * int param_3 = obj.top();
 * int param_4 = obj.getMin();
 */

224. 基本计算器

class Solution {
    public int calculate(String s) {
        Deque<Integer> ops = new LinkedList<>();
        ops.push(1);
        int sign = 1, ret = 0, n = s.length(), i = 0;
        while (i < n) {
            switch(s.charAt(i)){
                case ' ':
                    i++;
                    break;
                case '+':
                    sign = ops.peek();
                    i++;
                    break;
                case '-':
                    sign = -ops.peek();
                    i++;
                    break;
                case '(':
                    ops.push(sign);
                    i++;
                    break;
                case ')':
                    ops.pop();
                    i++;
                    break;
                default:
                    long num = 0;
                    while (i < n && Character.isDigit(s.charAt(i))) {
                        num = num * 10 + s.charAt(i) - '0';
                        i++;
                    }
                    ret += sign * num;
            }
        }
        return ret;
    }
}

316. 去除重复字母

这里也是一个小技巧
看到只包含小写字母这个字样,第一时间要想到
长度是 26 的数组

class Solution {
    public String removeDuplicateLetters(String s) {
        boolean[] vis = new boolean[26];
        int[] num = new int[26];
        for (int i = 0; i < s.length(); i++) {
            num[s.charAt(i) - 'a']++;
        }

        StringBuilder sb = new StringBuilder();
        int n;
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);
            if (!vis[ch - 'a']) {
                while ((n = sb.length()) > 0 && sb.charAt(n - 1) > ch) {
                    if (num[sb.charAt(n - 1) - 'a'] > 0) {
                        vis[sb.charAt(n - 1) - 'a'] = false;
                        sb.deleteCharAt(n - 1);
                    } else {
                        break;
                    }
                }
                vis[ch - 'a'] = true;
                sb.append(ch);
            }
            num[ch - 'a'] -= 1;
        }
        return sb.toString();
    }
}

402. 移掉 K 位数字

class Solution {
    public String removeKdigits(String num, int k) {
        StringBuilder res = new StringBuilder();
        int len = num.length(), n;
        for (int i = 0; i < len; i++){
            char cur = num.charAt(i);
            while (k > 0 && (n = res.length()) > 0 && res.charAt(n - 1) > cur ){
                res.deleteCharAt(n-1);
                k--;
            }
            if (res.length() == 0 && cur == '0') continue;
            res.append(cur);
        }
        while (k-- > 0 && res.length() > 0) res.deleteCharAt(res.length() - 1);
        return res.length() == 0 ? "0" : res.toString();
    }
}

503. 下一个更大元素 II

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int n = nums.length;
        int[] array = new int[2 * n], tmp = new int[2 * n];
        System.arraycopy(nums, 0, array, 0, n);
        System.arraycopy(nums, 0, array, n, n);
        Arrays.fill(tmp, -1);
        ArrayDeque<Integer> stack = new ArrayDeque<>();
        for(int i = 0; i < 2 * n; i++){
            while(!stack.isEmpty() && array[i] > array[stack.peek()]){
                tmp[stack.pop()] = array[i];
            }
            stack.push(i);
        }
        System.arraycopy(tmp, 0, nums, 0, n);
        return nums;
    }
}
class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int n = nums.length;
        int[] ret = new int[n];
        Arrays.fill(ret, -1);
        Deque<Integer> stack = new LinkedList<Integer>();
        for (int i = 0; i < n * 2 - 1; i++) {
            while (!stack.isEmpty() && nums[stack.peek()] < nums[i % n]) {
                ret[stack.pop()] = nums[i % n];
            }
            stack.push(i % n);
        }
        return ret;
    }
}

739. 每日温度

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int length = temperatures.length;
        int[] ans = new int[length];
        Deque<Integer> stack = new LinkedList<>();
        for (int i = 0; i < length; i++) {
            int t = temperatures[i];
            while (!stack.isEmpty() && t > temperatures[stack.peek()]) {
                int prevIndex = stack.pop();
                ans[prevIndex] = i - prevIndex;
            }
            stack.push(i);
        }
        return ans;
    }
}

844. 比较含退格的字符串

class Solution {
    public boolean backspaceCompare(String S, String T) {
        ArrayDeque<Character> stack1 = new ArrayDeque<>();
        ArrayDeque<Character> stack2 = new ArrayDeque<>();
        pushStack(stack1, S);
        pushStack(stack2, T);
        return stack1.toString().equals(stack2.toString());
    }

    private void pushStack(ArrayDeque<Character> stack, String s){
        for(char c: s.toCharArray()){
            if(c == '#'){
                if(!stack.isEmpty()){
                    stack.pop();
                }
            }else{
                stack.push(c);
            }
        }
    }
}
class Solution {
    public boolean backspaceCompare(String S, String T) {
        return build(S).equals(build(T));
    }

    public String build(String str) {
        StringBuffer ret = new StringBuffer();
        int length = str.length();
        for (int i = 0; i < length; ++i) {
            char ch = str.charAt(i);
            if (ch != '#') {
                ret.append(ch);
            } else {
                if (ret.length() > 0) {
                    ret.deleteCharAt(ret.length() - 1);
                }
            }
        }
        return ret.toString();
    }
}

1021. 删除最外层的括号

class Solution {
    public String removeOuterParentheses(String S) {
        StringBuilder sb = new StringBuilder();
        int level = 0;
        for (char c : S.toCharArray()) {
            if (c == ')') --level;
            if (level >= 1) sb.append(c);
            if (c == '(') ++level;
        }
        return sb.toString();
    }
}
import java.util.ArrayDeque
object Solution {
  def removeOuterParentheses(S: String): String = {
    val stack = new ArrayDeque[Char]()
    val res = new StringBuilder()
    var pre = 0
    for ((s, i) <- S.zipWithIndex) {
      if (stack.isEmpty) stack.push(s)
      else if (s == '(') stack.push(s)
      else stack.pop
      if (stack.isEmpty) {
        res.append(S.slice(pre + 1, i))
        pre = i + 1
      }
    }
    res.toString
  }
}

1047. 删除字符串中的所有相邻重复项

class Solution {
    public String removeDuplicates(String S) {
        char[] s = S.toCharArray();
        int top = -1;
        for (int i = 0; i < S.length(); i++) {
            if (top == -1 || s[top] != s[i]) {
                s[++top] = s[i];
            } else {
                top--;
            }
        }
        return String.valueOf(s, 0, top + 1);
    }
}
import java.util

object Solution {
  def removeDuplicates(S: String): String = {
    val stack = new util.ArrayDeque[Char]()
    stack.push(S(0))
    for (i <- S.indices if i > 0) {
      if (!stack.isEmpty && S(i) == stack.peek) stack.pop
      else stack.push(S(i))
    }
    stack.toArray.reverse.mkString
  }
}

1130. 叶值的最小代价生成树

class Solution {
    public int mctFromLeafValues(int[] A) {
        int res = 0;
        ArrayDeque<Integer> stack = new ArrayDeque<>();
        stack.push(Integer.MAX_VALUE);
        for (int a : A) {
            while (stack.peek() <= a) {
                res += stack.pop() * Math.min(stack.peek(), a);
            }
            stack.push(a);
        }
        while (stack.size() > 2) {
            res += stack.pop() * stack.peek();
        }
        return res;
    }
}

剑指 Offer 09. 用两个栈实现队列

class CQueue {
    private ArrayDeque<Integer> stackEnque;
    private ArrayDeque<Integer> stackDeque;

    public CQueue() {
        stackEnque = new ArrayDeque<>();
        stackDeque = new ArrayDeque<>();
    }

    public void appendTail(int value) {
        while(!stackDeque.isEmpty()){
            stackEnque.push(stackDeque.pop());
        }
        stackEnque.push(value);
    }

    public int deleteHead() {
        while(!stackEnque.isEmpty()){
            stackDeque.push(stackEnque.pop());
        }
        if(stackDeque.isEmpty()){
            return -1;
        }
        return stackDeque.pop();
    }
}

/**
 * Your CQueue object will be instantiated and called as such:
 * CQueue obj = new CQueue();
 * obj.appendTail(value);
 * int param_2 = obj.deleteHead();
 */
import java.util.ArrayDeque

class CQueue() {
  val in, out = new ArrayDeque[Int]()

  def appendTail(value: Int) {
    in.push(value)
  }

  def deleteHead(): Int = {
    if (out.isEmpty) {
      if (in.isEmpty) return -1
      while (!in.isEmpty) out.push(in.pop)
    }
    out.pop
  }
}

/**
 * Your CQueue object will be instantiated and called as such:
 * var obj = new CQueue()
 * obj.appendTail(value)
 * var param_2 = obj.deleteHead()
 */
  • 7
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值