回文串相关问题

130 阅读2分钟

统计回文子串数目【leetcode 647】

这个题目是在解答下一个题目时,想到能不能对查找回文子串进行优化,但是好像对下一个题目没有帮助。

  • 运行效率:

D5_K%89OTYM}7ZC376Z1X.png

  • 代码如下
/**
 * 【leetcode 647】给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。
 * @param s
 * @returns
 */
function countSubstrings(s: string): number {
  let res = 0;
  for (let i = 0; i < s.length; i++) {
    res++;
    res += isHuiWen(s, i - 1, i + 1);
    if (s.charAt(i) === s.charAt(i + 1)) {
      res += isHuiWen(s, i - 1, i + 2);
      res++;
    }
  }
  return res;
  function isHuiWen(s: string, i, j) {
    let res = 0;
    while (i >= 0 && j < s.length) {
      if (s.charAt(i) === s.charAt(j)) {
        res++;
        i--;
        j++;
      } else {
        break;
      }
    }
    return res;
  }
}

const res = countSubstrings("acbbc");

计算字符串所有可以切割为子回文串的分组【leetcode131】

这道题目用了三种解法,但是性能都是不太理想,又可以优化的地方,可以帮忙指导一下

  • 方法1,递归搜索
function partition1(s: string): string[][] {
  return getHuiWenGroup(s, s.length - 1);
}

function getHuiWenGroup(s: string, x: number): string[][] {
  let res = [];
  if (x < 0) {
    return [[]];
  }
  for (let i = x; i >= 0; i--) {
    if (isHuiWen(s, i, x)) {
      const temp = getHuiWenGroup(s, i - 1);
      temp.forEach((g) => g.push(s.substring(i, x + 1)));
      res = res.concat(temp);
    }
  }
  return res;
}
  • 方案二,递归动态规划
function partition2(s: string): string[][] {
  const dp = [];
  getHWGByDpRolls(s, s.length - 1);
  return dp[s.length - 1];
  function getHWGByDpRolls(s: string, x: number): string[][] {
    let res = [];
    if (x < 0) {
      return [[]];
    }
    for (let i = x; i >= 0; i--) {
      if (isHuiWen(s, i, x)) {
        if (!dp[i - 1]) {
          dp[i - 1] = getHWGByDpRolls(s, i - 1);
        }
        dp[i - 1].forEach((g) => res.push([...g, s.substring(i, x + 1)]));
      }
    }
    dp[x] = res;
    return res;
  }
}
  • 方案三,循环动态规划
function partition3(s: string): string[][] {
  const dp = [];
  dp[-1] = [[]];

  for (let i = 0; i < s.length; i++) {
    let temp = [];
    for (let j = i; j >= 0; j--) {
      if (isHuiWen(s, j, i)) {
        dp[j - 1].forEach((g) => {
          temp.push([...g, s.substring(j, i + 1)]);
        });
      }
    }
    dp[i] = temp;
  }

  return dp[s.length - 1];
}

上面几种方法运行效果都不太理想,想着堆isHuiWen进行优化,才做了第一道题,但是好像没用到。 希望大家懂得能指导一下

分割回文串【leetcode132】

  • 题目描述 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文。返回符合要求的 最少分割次数 。

  • 运行效率 效率其实不太理想

  • 代码:

function minCut(s: string): number {
  const dp = [];
  return minCutRolls(s, s.length - 1);

  function minCutRolls(s: string, index: number) {
    if (isHuiWen(s, 0, index) || index <= 0) {
      return 0;
    }
    let temp = Infinity;
    for (let i = index - 1; i >= 0; i--) {
      if (isHuiWen(s, i + 1, index)) {
        if (dp[i] === undefined) {
          dp[i] = minCutRolls(s, i);
        }
        if (dp[i] < temp) {
          temp = dp[i];
        }
      } else {
        continue;
      }
    }
    dp[index] = 1 + temp;
    return dp[index];
  }
}

工具函数isHuiWen方法

function isHuiWen(s: string, i: number = 0, j: number = s.length - 1) {
  while (i < j) {
    if (s.charAt(i) !== s.charAt(j)) return false;
    i++;
    j--;
  }
  return true;
}