赞
踩
回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili
例如从abc和def(n = 2)中各选出一个组成新的字符串?
如果n很大 , 这个时候for循环的表达能力有限 ;
这个增量构造答案的过程就是回溯的特点 ;
在递归到某一“叶子节点”(非最后一个叶子)时,答案需要向上返回,而此时还有其他的子树(与前述节点不在同一子树)未被递归到,又由于path为全局变量。若直接返回,会将本不属于该子树的答案带上去,故需要恢复现场。
恢复现场的方式为:在递归完成后 dfs(i+1); 后,进行与“当前操作”相反的操作,“反当前操作”。
这也就是n(n=8)个字符串中选两个的组合问题 ;
思路 :
1 . 先创建一个下标 与 对应字符串映射的数组,这里使用hash表进行映射也是可以的 ;
2 . 对于回溯 , 如果到了叶子节点 , 那么就直接添加即可 , 对于每一个path[i],都是存放digits[i]中数字字符对应字符串中的一个字符 , 遍历该字符串 , 对每一个字符进行递归操作 ;
3 . 对于不用恢复现场 : 因为每次递归到 i,一定会修改 path【i】,那么递归到终点时,每个 path【i】 都被覆盖成要枚举的字母,所以不需要恢复现场。
代码实现 :
- class Solution {
- public:
- const string mp[10] = {
- "", //0
- "", //1
- "abc", //2
- "def", //3
- "ghi", //4
- "jkl", //5
- "mno", //6
- "pqrs", //7
- "tuv", //8
- "wxyz", //9
- };
- vector<char> path ;
- vector<string> ans ;
- int n ;
-
- string get(){
- string tmp = "" ;
- for(char c : path){
- tmp += c ;
- }
- return tmp ;
- }
-
- void dfs(string digits , int i){
- // 先写递归终止条件
- if(i == n){
- ans.push_back(get()) ;
- return ; // 回溯
- }
- for(char c : mp[digits[i]-'0']){
- path[i] = c ;
- dfs(digits , i + 1) ;
- // 因为每一次path[i]都会被覆盖 , 那么就不用进行回溯
- }
- }
-
- vector<string> letterCombinations(string digits) {
- n = digits.size() ;
- if(n == 0) return ans ;
- path.resize(n) ;
- dfs(digits , 0) ;
- return ans ;
- }
- };
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
更加优雅的写法 :
- class Solution {
- string MAPPING[10] = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
- public:
- vector<string> letterCombinations(string digits) {
- int n = digits.length();
- if (n == 0) return {};
- vector<string> ans;
- string path(n, 0); // 本题 path 长度固定为 n
- function<void(int)> dfs = [&](int i) {
- if (i == n) {
- ans.emplace_back(path);
- return;
- }
- for (char c : MAPPING[digits[i] - '0']) {
- path[i] = c; // 直接覆盖
- dfs(i + 1);
- }
- };
- dfs(0);
- return ans;
- }
- };
-
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- class Solution {
- public:
- vector<vector<int>> ans ;
- vector<int> path ;
-
- void dfs(vector<int>& nums , int i){
- if(i==nums.size()){
- ans.push_back(path) ;
- return ;// 回溯
- }
- // 不选
- dfs(nums,i+1) ;// 不选i
-
- // 选
- path.push_back(nums[i]) ;
- dfs(nums,i+1) ;
- path.pop_back() ;
-
- }
-
- vector<vector<int>> subsets(vector<int>& nums) {
- if(nums.size()==0) return ans ;
- ans.clear() ;
- path.clear() ;
- dfs(nums,0) ;
- return ans ;
- }
- };
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
这样的话 每一个结点都是答案 ;
- class Solution {
- public:
- vector<vector<int>> ans;
- vector<int> path;
- void backtrack(vector<int>& nums,int idx){
- ans.push_back(path);
- if(idx >= nums.size()) return;
- for(int i=idx;i<nums.size();i++){
- path.push_back(nums[i]);
- backtrack(nums,i+1);
- path.pop_back();
- }
- }
- vector<vector<int>> subsets(vector<int>& nums) {
- path.clear();
- ans.clear();
- backtrack(nums,0);
- return ans;
- }
- };
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- class Solution {
- public:
- bool pd(string s , int l ,int r){
- while(l <= r){
- if(s[l++] != s[r--])
- return false;
- }
- return true ;
- }
-
- vector<vector<string>> ans ;
- vector<string> path ;
- int n = 0 ;
- // 答案视角 , 判断每一个子串结束的地方
-
- void dfs(string s , int i){
- if(i==n){
- ans.push_back(path) ;
- return ;
- }
- for(int j=i;j<n;j++){ // 枚举子串结束的位置
- if(pd(s,i,j)){
- path.push_back(s.substr(i,j-i+1)) ;
- dfs(s,j+1) ;
- path.pop_back();// 恢复现场
- }
- }
- }
-
-
- vector<vector<string>> partition(string s) {
- n = s.size() ;
- dfs(s,0) ;
- return ans ;
- }
- };
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
- class Solution {
- public:
- bool pd(string s , int l ,int r){
- while(l <= r){
- if(s[l++] != s[r--])
- return false;
- }
- return true ;
- }
-
- vector<vector<string>> partition(string s) {
- vector<vector<string>> ans ;
- vector<string> path ;
- // 判断每个逗号选或不选
- int n = s.size() ;
- // start 表示这一段回文串的开始位置
- function<void(int,int)> dfs = [&](int i,int start){
- if(i==n){
- ans.push_back(path) ;
- return ;
- }
- // 不选i-i+1
- if(i < n - 1){
- dfs(i+ 1, start) ;
- }
- // 选
- if(pd(s,start,i)){
- path.push_back(s.substr(start,i-start+1));
- dfs(i + 1 , i + 1 ) ;
- path.pop_back() ;
- }
- };
- dfs(0 , 0) ;
- return ans ;
- }
- };
![](https://csdnimg.cn/release/blogv2/dist/pc/img/newCodeMoreWhite.png)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。