数据结构与算法之LeetCode-241. 为运算表达式设计优先级

49 篇文章 0 订阅
43 篇文章 0 订阅

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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值