力扣131-分割字符串

本文详细介绍了如何使用回溯算法解决LeetCode第131题,即分割回文串的问题。通过分析题目、理解回溯法适用场景以及提供代码实现,解释了如何判断回文串并预处理回文串集合。最终展示了一个完整的C++解决方案,并附带了代码运行时间测试结果。
摘要由CSDN通过智能技术生成

第八十一天 --- 力扣131-分割字符串

题目一

力扣:131

在这里插入图片描述

思路

1、要先弄懂本题目是啥意思,要对s进行分割,分割出来的各个部分必须要是回文的,要求出所有可能的组合,这个一听,求出所有可能的情况,这个时候就要想到,可能是回溯算法,也有可能是DP,再看,是字符串分割问题,这种问题一般就是定位到回溯法暴力枚举所有可能的结果,用一些条件进行剪枝来优化。
2、到了这里我们来分析一下什么时候用回溯:
组合问题:N个数里面按一定规则找出k个数的集合
排列问题:N个数按一定规则全排列,有几种排列方式
切割问题:一个字符串按一定规则有几种切割方式
子集问题:一个N个数的集合里有多少符合条件的子集
棋盘问题:N皇后,解数独等等
3、回溯问题通用的一个模板:

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

4、综上,本体可以确定了,用回溯算法,回溯算法,最简单,最有效,最清晰的分析方法就是,画一棵树来分析:
在这里插入图片描述
所以当分析到了某个点i的时候,就要枚举从他开始的后面所有点,因为每一处都可能是分割点,如果能分割就递归走下去,分割条件就是是回文串,这也同样起到了剪枝的效果。
5、因为每一次都要回文串判断,所以我们想能不能在最短时间内判断是不是回文串,可以,用unordered_set,那前提得把所有可能的回文串存进去,所以我们要预处理,存进去所有回文串,用DP,这个就略过了,介绍过很多遍了。

代码

注意:
1、这里用的是全局量维护某一个答案,所以在回溯回来之后,说明刚才哪个分支已经完事了,所以要pop_back出去

class Solution {
public:
	vector<vector<string>> ans;//答案
	vector<string> tmp;//临时

	bool dp[100][100] = {};//DP
	unordered_set<string> item;//hash,快速判断回文串

	int n = 0;
	string s;

	void getArrange(int i) {//回溯法
		if (i == n) {//走到尽头,说明此分割有效
			ans.push_back(tmp);
			return;
		}
		for (int j = i; j < n; j++) {//枚举身后的,要从i开始,包括自己本身
			if (item.count(s.substr(i, j - i + 1))) {
				tmp.push_back(s.substr(i, j - i + 1));//加入临时答案
				getArrange(j + 1);//说明此次i-j合法,从j处分割,之后的进入递归
				tmp.pop_back();//分支完事,弹出,恢复现场
			}
		}
	}

	vector<vector<string>> partition(string s) {
		n = s.size();
		this->s = s;
		for (int i = 0; i < n; i++) {//DP预处理,初始化
			dp[i][i] = true;
			item.insert(s.substr(i, 1));
		}
		for (int i = 0; i < n - 1; i++) {//初始化
			if (s[i] == s[i + 1]) {
				dp[i][i + 1] = true;
				item.insert(s.substr(i, 2));
			}
		}
		for (int l = 2; l < n; l++) {
			for (int i = 0, j; i + l < n; i++) {
				j = i + l;
				if (s[i] == s[j] && dp[i + 1][j - 1]) {
					dp[i][j] = true;
					item.insert(s.substr(i, l + 1));
				}
			}
		}
		getArrange(0);
		return ans;
	}
};

(所有代码均已在力扣上运行无误)

经测试,该代码运行情况是(经过多次测试所得最短时间):

在这里插入图片描述

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JLU_LYM

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值