241. 为运算表达式设计优先级 - 力扣(LeetCode)
``
function diffWaysToCompute(expression: string): number[] {
const arr = new Array()
let cur = 0, count = 1
for (let i = 0; i < expression.length; i++) {
if (expression.charCodeAt(i) >= '0'.charCodeAt(0) && expression.charCodeAt(i) <= '9'.charCodeAt(0)) {
cur = cur * 10 + (expression.charCodeAt(i) - '0'.charCodeAt(0))
} else {
arr.push(cur)
arr.push(expression.charAt(i))
cur = 0
count++
}
}
arr.push(cur)
const dp = new Array(count).fill(0).map(() => new Array(count).fill(0).map(() => new Array<number>()))
const cal = function(left: number, right: number, op: string): number {
let ans = 0
switch (op) {
case "+":
ans = left + right
break
case "-":
ans = left - right
break
case "*":
ans = left * right
break
default:
}
return ans
}
const dfs = function(left: number, right: number): number[] {
const leftIdx = left >> 1, rightIdx = right >> 1
if (dp[leftIdx][rightIdx].length == 0) {
if (left == right) {
dp[leftIdx][rightIdx].push(arr[left])
} else {
for (let i = left + 1; i <= right - 1; i += 2) {
for (const leftRes of dfs(left, i - 1)) {
for (const rightRes of dfs(i + 1, right)) {
dp[leftIdx][rightIdx].push(cal(leftRes, rightRes, arr[i]))
}
}
}
}
}
return dp[leftIdx][rightIdx]
}
return dfs(0, arr.length - 1)
};
function diffWaysToCompute(expression: string): number[] {
if (/^\d+$/g.test(expression)) {
return [Number(expression)];
}
const regexp = /(?<operator>[\+\-\*])|(?<digit>\d+)/g;
const groups = Array.from(expression.matchAll(regexp)).map(
(a) => a.groups
) as unknown as (
| {
digit: string;
operator?: undefined;
}
| {
digit?: undefined;
operator: string;
}
)[];
const ans: number[] = diffWaysCalc(groups);
return ans;
}
function diffWaysCalc(
groups: (
| {
digit: number | string;
operator?: undefined;
}
| {
digit?: undefined;
operator: string;
}
)[]
): number[] {
if (groups.length === 1) {
return [Number(groups[0].digit)];
}
if (groups.length === 3) {
return [calc_three(groups)];
}
const ans: number[] = [];
for (let i = 1; i < groups.length; i += 2) {
const operator = groups[i];
const left = diffWaysCalc(groups.slice(0, i));
const right = diffWaysCalc(groups.slice(i + 1));
left
.map((a) =>
right.map((b) =>
calc_three([{ digit: a }, operator, { digit: b }])
)
).forEach(a=>ans.push(...a))
}
return ans;
}
function calc_three(
groups: (
| {
digit: number | string;
operator?: undefined;
}
| {
digit?: undefined;
operator: string;
}
)[]
): number {
if (groups.length === 3) {
const [a, b, c] = groups;
if (b.operator === "+") {
return Number(a.digit) + Number(c.digit);
}
if (b.operator === "-") {
return Number(a.digit) - Number(c.digit);
}
if (b.operator === "*") {
return Number(a.digit) * Number(c.digit);
}
}
throw Error("groups length not three or operator not +,-,*");
}
/**
* @param {string} expression
* @return {number[]}
*/
let memo = new Map();
var diffWaysToCompute = function (expression) {
// 避免重复计算
if (memo.has(expression)) {
return memo.get(expression);
}
let res = [];
for (let i = 0; i < expression.length; i++) {
let c = expression.charAt(i);
// 扫描算式 expression 中的运算符
if (c == "*" || c == "+" || c == "-") {
/****** 分 ******/
let left = diffWaysToCompute(expression.substring(0, i));
let right = diffWaysToCompute(expression.substring(i + 1));
/****** 治 ******/
// 通过子问题的结果,合成原问题的结果
for (let a of left) {
for (let b of right) {
switch (c) {
case "*":
res.push(a * b);
break;
case "+":
res.push(a + b);
break;
case "-":
res.push(a - b);
break;
}
}
}
}
}
// base case,递归函数必须有个 base case 用来结束递归,其实这段代码就是我们分治算法的 base case,代表着你「分」到什么时候可以开始「治」
// 如果 res 为空,说明算式是一个数字,没有运算符(因为当算式中不存在运算符的时候,就不会触发 if 语句,也就不会给res中添加任何元素)
if (!res.length) {
res.push(parseInt(expression));
}
// 将结果添加进备忘录
memo.set(expression, res);
return res;
};
执行结果:通过
执行用时:60 ms, 在所有 JavaScript 提交中击败了88.45%的用户
内存消耗:41.4 MB, 在所有 JavaScript 提交中击败了80.14%的用户
通过测试用例:25 / 25
function intersectionSizeTwo(intervals: number[][]): number {
intervals.sort((a, b) => {
if (a[1] != b[1]) {
return a[1] - b[1]
}
return b[0] - a[0]
})
let a = -1, b = -1, ans = 0
for (const [left, right] of intervals) {
if (left > b) {
a = right - 1
b = right
ans += 2
} else if (left > a) {
a = b
b = right
ans++
}
}
return ans
};
参考链接
241. 为运算表达式设计优先级 - 力扣(LeetCode)
[Python/Java/TypeScript/Go] 区间DP - 为运算表达式设计优先级 - 力扣(LeetCode)
正则+分治,速度超过94% - 为运算表达式设计优先级 - 力扣(LeetCode)
利用分治算法解决:思路详尽、代码简洁、注释详细 - 为运算表达式设计优先级 - 力扣(LeetCode)
[Python/Java/TypeScript/Go] 贪心 - 设置交集大小至少为2 - 力扣(LeetCode)