lc54. 螺旋矩阵(MD)

给你一个 mn 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。

示例 1:

img

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]

示例 2:

img

输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

提示:

  • m == matrix.length
  • n == matrix[i].length
  • 1 <= m, n <= 10
  • -100 <= matrix[i][j] <= 100

手动模拟一下就可以

class Solution {
public List<Integer> spiralOrder(int[][] matrix) {
List<Integer> res = new ArrayList<>();
if (matrix.length == 0 || matrix[0].length == 0) {
return res;
}
int l = 0, r = matrix[0].length - 1, t = 0, b = matrix.length - 1;
while (l <= r && t <= b) {
for (int j = l; j <= r; j++) {
res.add(matrix[t][j]);
}
for (int i = t + 1; i <= b; i++) {
res.add(matrix[i][r]);
}
if (l < r && t < b) {
for (int j = r - 1; j > l; j--) {
res.add(matrix[b][j]);
}
for (int i = b; i > t; i--) {
res.add(matrix[i][l]);
}
}
t++;
b--;
r--;
l++;
}
return res;
}
}

lc20. 有效的括号(EZ)

给定一个只包括 '('')''{''}''['']' 的字符串 s ,判断字符串是否有效。

有效字符串需满足:

  1. 左括号必须用相同类型的右括号闭合。
  2. 左括号必须以正确的顺序闭合。
  3. 每个右括号都有一个对应的相同类型的左括号。

示例 1:

输入:s = "()"
输出:true

示例 2:

输入:s = "()[]{}"
输出:true

示例 3:

输入:s = "(]"
输出:false

提示:

  • 1 <= s.length <= 104
  • s 仅由括号 '()[]{}' 组成

栈的入门题,简单

class Solution {
public boolean isValid(String s) {
Stack<Character> stk = new Stack<>();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (ch == '(' || ch == '[' || ch == '{') {
stk.push(ch);
} else {
if (ch == ')') {
if (!stk.isEmpty() && stk.peek() == '(') {
stk.pop();
} else {
return false;
}
} else if (ch == ']') {
if (!stk.isEmpty() && stk.peek() == '[') {
stk.pop();
} else {
return false;
}
} else {
if (!stk.isEmpty() && stk.peek() == '{') {
stk.pop();
} else {
return false;
}
}
}
}
return stk.isEmpty();
}
}

lc155. 最小栈(MD)

设计一个支持 pushpoptop 操作,并能在常数时间内检索到最小元素的栈。

实现 MinStack 类:

  • MinStack() 初始化堆栈对象。
  • void push(int val) 将元素val推入堆栈。
  • void pop() 删除堆栈顶部的元素。
  • int top() 获取堆栈顶部的元素。
  • int getMin() 获取堆栈中的最小元素。

示例 1:

输入:
["MinStack","push","push","push","getMin","pop","top","getMin"]
[[],[-2],[0],[-3],[],[],[],[]]

输出:
[null,null,null,null,-3,null,0,-2]

解释:
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.

提示:

  • -2^31 <= val <= 2^31 - 1
  • poptopgetMin 操作总是在 非空栈 上调用
  • push, pop, top, and getMin最多被调用 3 * 10^4

关键是在于怎么保存这个最小值,以及在pop之后如何获取到上一次的最小值(回滚之后如何获取最小值)

介于考虑到栈可能会pop,而pop前后的最小值可能是有变化的,所以在原来储存基本数据的栈之外,我们还需要额外创建一个专门储存最小值的栈,这样即使是发生了pop我们也能获得pop后的最小值

class MinStack {
private Stack<Integer> stk = new Stack<>();
private Stack<Integer> minStk = new Stack<>();

public MinStack() {
minStk.push(Integer.MAX_VALUE);
}

public void push(int val) {
stk.push(val);
minStk.push(Math.min(minStk.peek(), val));
}

public void pop() {
stk.pop();
minStk.pop();
}

public int top() {
return stk.peek();
}

public int getMin() {
return minStk.peek();
}
}

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

lc150. 逆波兰表达式求值(MD)

给你一个字符串数组 tokens ,表示一个根据 逆波兰表示法 表示的算术表达式。

请你计算该表达式。返回一个表示表达式值的整数。

注意:

  • 有效的算符为 '+''-''*''/'
  • 每个操作数(运算对象)都可以是一个整数或者另一个表达式。
  • 两个整数之间的除法总是 向零截断
  • 表达式中不含除零运算。
  • 输入是一个根据逆波兰表示法表示的算术表达式。
  • 答案及所有中间计算结果可以用 32 位 整数表示。

示例 1:

输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

示例 2:

输入:tokens = ["4","13","5","/","+"]
输出:6
解释:该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6

示例 3:

输入:tokens = ["10","6","9","3","+","-11","*","/","*","17","+","5","+"]
输出:22
解释:该算式转化为常见的中缀算术表达式为:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22

提示:

  • 1 <= tokens.length <= 104
  • tokens[i] 是一个算符("+""-""*""/"),或是在范围 [-200, 200] 内的一个整数

逆波兰表达式:

逆波兰表达式是一种后缀表达式,所谓后缀就是指算符写在后面。

  • 平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 )
  • 该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * )

逆波兰表达式主要有以下两个优点:

  • 去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
  • 适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中

这道题的难度,不应该被评为mid,应该改成easy,因为这道题就是学数据结构的时候最基本的一道例题——后缀表达式计算。我不相信有哪个学校哪个计算机学院的计算机专业讲数据结构这门课的时候是没有讲过这个经典例子的

class Solution {
public int evalRPN(String[] tokens) {
Deque<Integer> deq = new LinkedList<>();
for (String s : tokens) {
if ("+".equals(s)) {
deq.push(deq.pop() + deq.pop());
} else if ("-".equals(s)) {
deq.push(-deq.pop() + deq.pop());
} else if ("*".equals(s)) {
deq.push(deq.pop() * deq.pop());
} else if ("/".equals(s)) {
int num1 = deq.pop();
int num2 = deq.pop();
deq.push(num2 / num1);
} else {
deq.push(Integer.valueOf(s));
}
}
return deq.pop();
}
}