前言
本文隶属于专栏《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()
*/