LeetCode 分割回文串II(动态规划)

给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串。
返回符合要求的最少分割次数。
示例:

输入: "aab"
输出: 1
解释: 进行一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。

请先翻阅 LeetCode 分割回文子串
此题就是在上一题将所有分割方法修改为最少的分割次数。
方法一:回溯法。继续使用上一题的代码,只是在dfs函数中添加一个变量记录分割的次数,并寻找到分割次数最少的分割方法。(但是超时了。。。)

class Solution {
public:
	int minResult = INT_MAX;
	int minCut(string s) {
		if (s == "") {
			return 0;
		}
		dfs(s, 0, 0);//开始搜索
		return minResult;
	}
	//从beginIndex开始,寻找回文子串
	void dfs(string &str, int beginIndex, int steps) {
		int strSize = str.size();
		if (beginIndex == strSize) {//如果截取到了尾端,说明寻找到了一个解
			minResult = min(minResult, steps - 1);
			return;
		}
		//对截取长度进行穷举
		int endIndex = strSize - 1;
		while (endIndex >= beginIndex) {
			if (isPalindrome(str, beginIndex, endIndex)) {//如果当前截取的[beginIndex, endIndex]段是回文串
				dfs(str, endIndex + 1, steps + 1);//以endIndex + 1下标为起始,继续寻找
			}
			--endIndex;
		}
	}
	//判断在str串中截取[beginIndex, endIndex]段是否是回文串
	bool isPalindrome(string &str, int beginIndex, int endIndex) {
		while (beginIndex < endIndex) {
			if (str[beginIndex++] != str[endIndex--]) {
				return false;
			}
		}
		return true;
	}
};

在这里插入图片描述
方法二:动态规划。

class Solution {
public:
	int minCut(string s) {
		if (s == "") {
			return 0;
		}
		int strSize = s.size();
		vector<vector<bool>> judge(strSize, vector<bool>(strSize, false));//judge[j][i]用于记录s串[i,j]是否是回文
		vector<int> dp(strSize, INT_MAX);//dp[i]用于记录s串中[0, i]需要分割的次数
		for (int i = 0; i < strSize; ++i) {
			for (int j = 0; j <= i; ++j) {//从[j, i]
				if (s[i] == s[j] && (i - j <= 1 || judge[j + 1][i - 1])) {
					judge[j][i] = true;
					if (j != 0) {//如果j == 0,说明[0, i]都是回文
                        //dp[j - 1] + 1 表示的分割[0, j - 1] + [j, i]需要分割的次数一个解
						dp[i] = min(dp[i], dp[j - 1] + 1);
					}
					else {
						dp[i] = 0;
					}
				}
			}
		}
		return dp[strSize - 1];
	}
};

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_41855420/article/details/87886243