问题一
计算器: https://leetcode-cn.com/problems/calculator-lcci/
思路:将数字与操作符分开,然后第一遍计算乘除法,第二遍计算加减法。
例如:3 + 4 * 4 / 2
操作: + * /
数字:3 4 4 2
操作符的个数比数字少一个,将操作符一一从栈中弹出,就可以依次计算完成。
public int calculate(String s) {
char[] arr = s.toCharArray();
// 将数字与操作符分开,数字的个数比操作数多一个
List<Integer> numList = new ArrayList<>();
List<Character> opList = new ArrayList<>();
StringBuilder sb;
for (int i = 0; i < arr.length;) {
if (arr[i] == ' ') {
i++;
} else if (arr[i] == '+' || arr[i] == '-' || arr[i] == '*' || arr[i] == '/') {
opList.add(arr[i]);
i++;
} else {
sb = new StringBuilder();
int j = i;
for (; j < arr.length; j++) {
if ("0123456789".indexOf(arr[j]) >= 0) {
sb.append(arr[j]);
} else {
break;
}
}
i = j;
numList.add(Integer.valueOf(sb.toString()));
}
}
// 按照计算表从右到左推入栈中(从栈中取出的时候即为表达式正常顺序),并计算乘除法
Stack<Integer> numStack = new Stack<>();
Stack<Character> opStack = new Stack<>();
Stack<Integer> leftNumStack = new Stack<>();
Stack<Character> leftOpStack = new Stack<>();
for (int i = numList.size() - 1; i >= 0; i--) {
numStack.push(numList.get(i));
}
for (int i = opList.size() - 1; i >= 0; i--) {
opStack.push(opList.get(i));
}
leftNumStack.push(numStack.pop());
while (!opStack.isEmpty()) {
Character op = opStack.pop();
// 加减法,直接把数字和符号入栈
if (op == '+' || op == '-') {
leftNumStack.push(numStack.pop());
leftOpStack.push(op);
} else {
// 乘除法,计算完成后,将计算结果入栈
int result;
if (op == '*') {
result = leftNumStack.pop() * numStack.pop();
} else {
result = leftNumStack.pop() / numStack.pop();
}
leftNumStack.push(result);
}
}
// 计算加减法,
int result;
if (!leftOpStack.isEmpty()) {
// 反转栈中的元素,变成有序计算,因为有减法存在,所有不能逆序计算
opStack.clear();
numStack.clear();
while (!leftOpStack.isEmpty()) {
opStack.push(leftOpStack.pop());
}
while (!leftNumStack.isEmpty()) {
numStack.push(leftNumStack.pop());
}
result = numStack.pop();
while (!opStack.isEmpty()) {
char op = opStack.pop();
if (op == '+') {
result = numStack.pop() + result;
} else {
result = result - numStack.pop();
}
}
} else {
result = leftNumStack.pop();
}
return result;
}
问题二
每日温度:https://leetcode-cn.com/problems/daily-temperatures/
思路:最先想到的是暴力求解。做完后看了解答,可以使用逆向计算,加上跳跃的方式。
public int[] dailyTemperatures(int[] T) {
// 思路:暴力求解,依次遍历整个数组,为求出下次的高温,再依次遍历后面的所有温度
int currentVal = 0, tmpVal = 0;
int[] result = new int[T.length];
for (int i = 0; i < T.length - 1; i++) {
currentVal = T[i];
for (int j = i + 1; j < T.length; j++) {
tmpVal = T[j];
if (tmpVal > currentVal) {
result[i] = j - i;
break;
}
}
}
return result;
}
// 逆向遍历,使用跳跃的形式
public int[] dailyTemperatures2(int[] T) {
int[] result = new int[T.length];
for (int i = T.length - 1; i >= 0; i--) {
for (int j = i + 1; j < T.length;) {
// 如果找到等于或者大于当前值的情况,则直接跳跃
if (T[i] < T[j]) {
result[i] = j - i;
break;
} else if (T[i] == T[j]) {
if (result[j] > 0) {
result[i] = j - i + result[j];
}
break;
} else {
// T[i] > T[j]的情况,如果存在比T[j]大的值,则直接跳跃到该值;如果不存在比T[j]大的值,那么一定不存在比T[i]大的值
if (result[j] > 0) {
j = j + result[j];
} else {
break;
}
}
}
}
return result;
}
注:第四周才加入,补做第三周的习题。