当前位置:网站首页>【每日一题】241. 为运算表达式设计优先级
【每日一题】241. 为运算表达式设计优先级
2022-07-02 18:54:00 【王六六的IT日常】
- 递归
把字符串按照操作符分割为两个子表达式,将两个子表达式的结果集进行当前op的操作,组装成新的结果集,对每个op分别进行分割得到的结果集之和就是最终的答案。而子表达式又是相同的问题,可以采用递归进行计算,最终会递归到一个digit上。
class Solution {
public List<Integer> diffWaysToCompute(String expression) {
//表达式为空
if (expression == null || expression.length() == 0) {
return new ArrayList<>();
}
char[] chars = expression.toCharArray();
List<Integer> ans = new ArrayList<>();
for (int i = 0; i < chars.length; i++) {
char aChar = chars[i];
//如果当前字符是操作符,也就是op,进行分割
if (!Character.isDigit(aChar)) {
//递归拿到左右两个表达式的结果集
List<Integer> leftList = diffWaysToCompute(expression.substring(0, i));
List<Integer> rightList = diffWaysToCompute(expression.substring(i + 1));
//对两个结果集的所有结果进行op运算
for (Integer left : leftList) {
for (Integer right : rightList) {
if (aChar == '+') {
ans.add(left + right);
} else if (aChar == '-') {
ans.add(left - right);
} else {
ans.add(left * right);
}
}
}
}
}
//结果集是空,证明该字符串是数字,将数字加入结果集
if (ans.isEmpty()) {
ans.add(Integer.valueOf(expression));
}
return ans;
}
}
- 动态规划
因为最终的答案是由一个个子问题(子表达式)的答案所构成,所以可以采用动态规划,将问题划分为一个个子问题来求解。
首先我们将字符串分成digit、op、digit、op、digit、op、digit…这样的序列,并且可知序列的长度是奇数个,所以子问题的最小长度为3(长度为1的digit不需要计算),也就是一个op运算需要至少三个元素(两个digit和一个op),下一个子问题的长度为当前子问题+2(加一个op和一个digit),所以我们可以从最小长度为3的子问题一步步求解最大长度的解。
class Solution {
public List<Integer> diffWaysToCompute(String expression) {
List<Object> ops = new ArrayList<>();
//将字符串分割为digit、op、digit、op、digit......这样的序列
for (int i = 0; i < expression.length(); ) {
if (!Character.isDigit(expression.charAt(i))) {
//添加操作符
ops.add(expression.charAt(i));
i++;
} else {
//添加数字
int digit = 0;
while (i < expression.length() && Character.isDigit(expression.charAt(i))) {
digit = digit * 10 + expression.charAt(i) - '0';
i++;
}
ops.add(digit);
}
}
//dp[i][j]表示从i到j子问题(子表达式)的所有答案
List<Integer>[][] dp = new List[ops.size()][ops.size()];
for (int i = 0; i < ops.size(); i++) {
for (int j = 0; j < ops.size(); j++) {
dp[i][j] = new ArrayList<>();
}
}
//初始时,所有的digit都是自己本身并且数字都是隔着存放的,并且位置固定在偶数位(0,2,4...) 所以+2
//eg:digit、op、digit、op、digit......
for (int i = 0; i < ops.size(); i += 2) {
dp[i][i].add((int) ops.get(i));
}
//从长度为3的子问题开始计算
for (int len = 3; len <= ops.size(); len += 2) {
//左边界从0开始
for (int left = 0; left + len <= ops.size(); left += 2) {
//右边界
int right = left + len - 1;
//按照op进行分割左右两个子表达式 +2表示下一个op
for (int k = left + 1; k < right; k += 2) {
List<Integer> leftAns = dp[left][k - 1];
List<Integer> rightAns = dp[k + 1][right];
//对左右两个子表达式的结果集进行合并处理
for (int num1 : leftAns) {
for (int num2 : rightAns) {
char op = (char) ops.get(k);
if (op == '+') {
dp[left][right].add(num1 + num2);
} else if (op == '-') {
dp[left][right].add(num1 - num2);
} else if (op == '*') {
dp[left][right].add(num1 * num2);
}
}
}
}
}
}
return dp[0][ops.size() - 1];
}
}
class Solution {
char[] cs;
public List<Integer> diffWaysToCompute(String s) {
cs = s.toCharArray();
return dfs(0, cs.length - 1);
}
List<Integer> dfs(int l, int r) {
List<Integer> ans = new ArrayList<>();
for (int i = l; i <= r; i++) {
if (cs[i] >= '0' && cs[i] <= '9') continue;
List<Integer> l1 = dfs(l, i - 1), l2 = dfs(i + 1, r);
for (int a : l1) {
for (int b : l2) {
int cur = 0;
if (cs[i] == '+') cur = a + b;
else if (cs[i] == '-') cur = a - b;
else cur = a * b;
ans.add(cur);
}
}
}
if (ans.isEmpty()) {
int cur = 0;
for (int i = l; i <= r; i++) cur = cur * 10 + (cs[i] - '0');
ans.add(cur);
}
return ans;
}
}
边栏推荐
- Yes, that's it!
- 搭建哨兵模式reids、redis从节点脱离哨兵集群
- Solution: vs2017 cannot open the source file stdio h main. H header document [easy to understand]
- 程序猿入门攻略(十二)——数据的存储
- AcWing 1134. Shortest circuit counting problem solution (shortest circuit)
- Registration opportunity of autowiredannotationbeanpostprocessor under annotation development mode
- 自動生成VGG圖像注釋文件
- Common problems and description of kt148a voice chip IC development
- AcWing 383. Sightseeing problem solution (shortest circuit)
- Start practicing calligraphy
猜你喜欢
Refactoring: improving the design of existing code (Part 2)
为什么我对流程情有独钟?
字典
KT148A语音芯片ic的硬件设计注意事项
SQLite 3.39.0 发布,支持右外连接和全外连接
Set up sentinel mode. Reids and redis leave the sentinel cluster from the node
Kt148a voice chip instructions, hardware, protocols, common problems, and reference codes
程序猿入门攻略(十二)——数据的存储
ShardingSphere-JDBC5.1.2版本关于SELECT LAST_INSERT_ID()本人发现还是存在路由问题
One side is volume, the other side is layoff. There are a lot of layoffs in byte commercialization department. What do you think of this wave?
随机推荐
AcWing 1137. Select the best line solution (the shortest circuit)
RPD出品:Superpower Squad 保姆级攻略
Implementation of 452 strcpy, strcat, StrCmp, strstr, strchr
rxjs Observable 自定义 Operator 的开发技巧
LeetCode 0871. Minimum refueling times - similar to poj2431 jungle adventure
多态的理解以及作用
Refactoring: improving the design of existing code (Part 1)
AcWing 340. 通信线路 题解(二分+双端队列BFS求最短路)
Infix expression is converted to suffix expression (C language code + detailed explanation)
What are the benefits of multi terminal applet development? Covering Baidu applet, Tiktok applet, wechat applet development, and seizing the multi platform traffic dividend
SQLite 3.39.0 发布,支持右外连接和全外连接
AcWing 1126. 最小花费 题解(最短路—dijkstra)
[ERP software] what are the dangers of the secondary development of ERP system?
AcWing 341. 最优贸易 题解 (最短路、dp)
中缀表达式转换为后缀表达式(C语言代码+详解)
checklistbox控件用法总结
《代碼整潔之道》讀書筆記
Detailed explanation of VBScript (I)
JS如何取整数
Idea editor removes SQL statement background color SQL statement warning no data sources are configured to run this SQL And SQL dialect is not config