递归 构成合法不同颜色字符串的数量

80 阅读1分钟

题目

3dee54422f8245370746f83e101b6a29.png

  • 题目还要求配对的括号颜色必须一样
  • 假设当前字符串是一个合法字符串,已经确定的左括号为 a 个,数组长度为 len,颜色的种类为 k,则自由选择颜色的方案数为 k^(len-a*2)/2
  • 所以问题转换成了求合法的字符串数量 s,最终方案数量为 s*k^(len-a*2)/2
function main(arr, k) {
  // 括号的方案
  let funcs = process(arr, 0, 0);

  let colors = 0;
  for (let i = 0; i < arr.length; i++) {
    if (arr[i] !== 0) {
      colors++;
    }
  }
  // 每种括号方案下,颜色的方案
  colors = Math.pow(k, (arr.length - colors * 2) / 2);

  return funcs * colors;
}

// i 来到的位置
// j [0,i-1]区间里左括号比右括号多多少个
function process(arr, i, j) {
  // 来到终止位置时,左括号比右括号多0个表示合法
  if (i === arr.length) {
    return j === 0 ? 1 : 0;
  }

  // 任何一个时刻前缀的左括号都不能小于右括号数量
  if (j < 0) {
    return 0;
  }

  // 剩余字符数量比左括号多余数量少
  if (arr.length - i < j) {
    return 0;
  }

  // 说明是左括号
  if (arr[i] !== 0) {
    return process(arr, i + 1, j + 1);
  } else {
    // 当前位置选左括号
    let p1 = process(arr, i + 1, j + 1);
    // 当前位置选右括号
    let p2 = process(arr, i + 1, j - 1);
    return p1 + p2;
  }
}