所有计算结果为100的字符串组合

249 阅读1分钟

题目要求

/**
 * 将1~9之间任意位置插入+、-、'',输出所有计算结果为100的字符串组合
 * 比如:1+2+3-4+5+6+78+9
 * 1+2+3-4+5+6+78+9和+1+2+3-4+5+6+78+9视为同一种结果,只需要输出1+2+3-4+5+6+78+9
 */

题目解析

对于每一个数字前面分情况进行插入,可以分别插入+、-或者不插入任何值,然后通过深度优先遍历+回溯的方式列举所有结果,并对结果进行计算过滤,将满足条件的所有组合记录下来即可。

题解

let combNum = function () {
  let nums = '123456789';
  let opers = ['+', '-', ''];
  let res = [];
  let track = [];
  const length = nums.length;
  backtrack(track, 0);
  return res;

  /**
   * 深度优先遍历+回溯,列举出所有场景,然后按照题目要求进行过滤即可
   */
  function backtrack(track, index) {
    if (track.length === length) {
      let resStr = track.join('');
      // 开头有+和没有视为一种情况,所以需要排除掉以+开头的场景
      if (resStr[0] != '+' && calc(resStr) === 100) {
        res.push(resStr);
      }
      return;
    }
    for (let i = index; i < length; i++) {
      const num = nums[i];
      for (const oper of opers) {
        track.push(oper + num);
        backtrack(track, i + 1);
        track.pop();
      }
    }
  }

  /**
   * 计算字符串的值,比如:1+23-4+5+6+78-9=100
   */
  function calc(s) {
    let num = 0;
    let oper = '+';
    let res = [];
    for (let index = 0, length = s.length; index < length; index++) {
      const char = s[index];
      // 连续是数字的场景,比如'78'转为78
      if (isDigit(char)) {
        num = num * 10 + (char - '0');
      }
      // 遇到非数字或者已经遍历结束的时候需要根据操作符类型将数字入栈
      // 此处可以扩展如果有*/等操作在下面分别计算即可
      // 需要注意*/的时候将最后一个操作数出栈与当前数字计算后入栈
      if (!isDigit(char) || index === length - 1) {
        if (oper === '+') {
          res.push(num);
        }
        if (oper === '-') {
          res.push(-num);
        }
        // 上一个数字计算结束将操作符替换为最新的,并且将操作数重置
        oper = char;
        num = 0;
      }
    }
    // 最终将栈里面所有数累加起来即可
    return res.reduce((a, b) => a + b);
  }

  function isDigit(char) {
    // 此处也可以用正则表达式判断,但是正则比较耗时,此处因为知道确切范围直接判断即可
    return nums.includes(char);
  }
}

欢迎有更好解题思路的掘友留言交流。