HOT61-分割回文串

         leetcode原题链接分割回文串

         上一篇HOT60-单词搜索

         下一篇:HOT62-N皇后

题目描述

        给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。回文串 是正着读和反着读都一样的字符串。

示例 1:

输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]

示例 2:

输入:s = "a"
输出:[["a"]]

提示:

  • 1 <= s.length <= 16
  • s 仅由小写英文字母组成

解题方法: 回溯法。定义backtrack(s, i, tmp, result)表示以i为当前分割的起点,从[i, n)中获取回文串。然后遍历不同的j=i+len,如果[i,j]是回文串,则下一段查找从j+1开始,详细见代码注释。另外,值得一提的是如何判断s[i...j]是否为回文串,方法如下:

方法1: 双指针法(在本题中的缺陷是有重复计算)

方法2: 动态规划法。dp[i][j]表示str[i...j]是否为回文串

dp[i-1][j+1] = dp[i][j] && s[i-1]==s[j+1]

从左右等号两边的i,j关系可以看出,二维数组初始化遍历的顺序i是从大到下,j是从小到大。

C++代码

#include <iostream>
#include <vector>
#include <string> 
/*
   abcb
   方法1: 双指针法(在本题中的缺陷是有重复计算)
   方法2: 动态规划法。dp[i][j]表示str[i...j]是否为回文串
   dp[i-1][j+1] = dp[i][j] && s[i-1]==s[j+1]

*/
class Solution {
public:
    std::vector<std::vector<std::string>> partition(std::string s) {
        std::vector<std::string> tmp;
        std::vector<std::vector<std::string>> result;
        backtrack(s, 0, tmp, result);
        return result;
    }

    void backtrack(const std::string& s,
                   int i,
                   std::vector<std::string>& tmp,
                   std::vector<std::vector<std::string>>& result) { //以i为起点
        int n = s.size();
        if (i == n) {
            result.emplace_back(tmp);
        }
        for (int j = i; j < n; j++) {
            int len = j - i + 1; // [i, ..., j]
            if (check(s, i, j)) { // 判断 [i, j]是否为回文串
                tmp.push_back(s.substr(i, len)); // 选择[i...j]
                backtrack(s, j + 1, tmp, result); //继续从j的下一个位置开始选择
                tmp.pop_back(); //撤销选择
            }
        }
        
    }
    // 判断s[i,...,j]是否为回文串,这里用的是最朴素的方法。
    // 当然可以用动态规划优化,可以减少重复计算:
    // 动态规划优化的方法是用dp[i][j]保存s[i,...,j]是否为回文串
    //    状态转移方程:dp[i-1][j+1] = dp[i][j] && s[i-1]==s[j+1]
    //    初始化顺序:i从大到小,j从小到大 (根据等号两边i,j的大小可以看出)
    bool check(const std::string& s, int i, int j) {
        while (i <= j) {
            if (s[i] != s[j]) {
                return false;
            }
            i++;
            j--;
        }
        return true;
    }

};

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值