Skip to content
本页目录

其它回溯篇

分割回文子字符串

剑指 Offer II 086. 分割回文子字符串

回溯 + 记忆搜索

JavaScript
const partition = s => {
  const [ret, len] = [[], s.length]
  const pali = Array(len)

  for (let i = 0; i < len; i++) {
    pali[i] = Array(len)
  }

  const isPali = (s, l, r) => {
    while (l < r) {
      if (s[l] !== s[r]) {
        pali[l][r] = false
        return false
      }
      l++
      r--
    }
    pali[l][r] = true
    return true
  }

  const dfs = (path, idx) => {
    // 指针越界了,没有可以切分的子串了
    // 递归到这一步,说明一直在切出回文串,现在生成了一个合法的部分解
    if (idx === len) {
      ret.push([...path])
      return
    }
    for (let i = idx; i < len; i++) {
      if (pali[idx, i] === false) continue
      if (pali[idx][i] || isPali(s, idx, i)) {
        path.push(s.substring(idx, i + 1))
        dfs(path, i + 1)
        path.pop()
      }
    }
  }
  dfs([], 0)
  return ret
}

时间复杂度:O(n*2^n);空间复杂度:O(n^2)

生成匹配的括号

剑指 Offer II 085. 生成匹配的括号

回溯

JavaScript
const generateParenthesis = n => {
  const ret = []
  const dfs = (path, l, r) => {
    // 字符串构建完成
    if (path.length === 2 * n) {
      ret.push(path)
      return
    }
    // 只要 ( 有剩,就优先选 (
    if (l > 0) dfs(path + '(', l - 1, r)
    // ) 剩的比 ( 多,才能选 )
    if (r > l) dfs(path + ')', l, r - 1)
  }
  dfs('', n, n)
  return ret
}

复原 IP

剑指 Offer II 087. 复原 IP

回溯

JavaScript
const restoreIpAddresses = s => {
  const [ret, len] = [[], s.length]

  const dfs = (path, idx) => {
    // 片段满4段,且耗尽所有字符
    if (path.length === 4 && idx === len) {
      ret.push(path.join('.'))
      return
    }
    // 满4段,字符未耗尽,不用往下选了
    if (path.length === 4 && idx < len) return

    for (let i = 1; i < 4; i++) {  // 枚举出选择,每段三种切割长度
      if (idx + i - 1 >= len) return  // 加上要切的长度就越界,不能切这个长度
      if (i !== 1 && s[idx] === '0') return  // 不能切出'0x'、'0xx'
      const str = s.substring(idx, idx + i)
      if (i === 3 && +str > 255) return  // 当前切出的片段不能超过255
      path.push(str)
      dfs(path, idx + i)
      path.pop()
    }
  }
  dfs([], 0)
  return ret
}