回溯法

###读入一行 char ch[100];cin.getline(ch,100);string str;getline(cin,str);

###优先队列  priority_queue<int,vector<int>,greater<int>> que;//升序,小顶堆

struct ListNode {
     int val;
     ListNode *next;
     ListNode() : val(0), next(nullptr) {}
     ListNode(int x) : val(x), next(nullptr) {}
     ListNode(int x, ListNode *next) : val(x), next(next) {}
 };
struct cmp{
        bool operator ()(ListNode *a, ListNode *b){
            return a->val>b->val;
        }
    };
priority_queue<ListNode*,vector<ListNode*>,cmp> que;

还有一种结构体内重载

struct Status {
int val;
ListNode *ptr;
bool operator < (const Status &rhs) const {
return val > rhs.val;
}
};

priority_queue <Status> q;

###位运算  负数取余1判断奇偶,只能用&1不能用%。同时如果先判断偶数注意括号,if((n&1) == 0)

###集合查询, if(uset.find(nums[i]) != uset.end())//去重

###图遍历  unordered_map<int,int> map;

第一种  注意这里x是指针,->取值

        for(auto x = map.begin();x!=map.end();x++){
            if(x->second == 1)
                return x->first;
        }
第二种  注意这里x是 . 取值,&表示传地址共用一个地址不创建新的空间
for(auto &x : map){
            if(x.second() == 1)
                return x.first();
        }

###队列有que,size()方法,层序遍历  q.push(x)  q.pop()  q.front()  q.back()  q.empty()

###字符串也有push_back(0),pop_back()方法,17题

###字符串的增加和删除,s = s.insert(cur,text); s.erase(0, cnt);都比substr快

###字符串找子串,s.find("123");s.find("123",0);第一个参数子串;第二个参数查找的起始位置

###字符串反转自身,reverse(s.begin(),s.end())

###string切割, s.substr(pos, len)

###数字转字符串 string s = to_string(num);

###字符串转数字 int num = stoi(s);

###vector全局声明定义会报错expected parameter declarator vector<int>father(200); ,全局声明,主函数里定义。vector<int>a;a = vector<int>(n,0);

###vector转字符串 Str.assign(Vec.begin(), Vec.end());

###vector反转自身,reverse(vec.begin(),vec.end())

###vector排序,只有两个参数,sort(path.begin(),path.end());vector可直接赋值给另外一个vec,也可以直接判等,39题
###vector取最后一个元素 path.back()
###vector删除元素  vec.erase(vec.begin()+5);//erase the 6th element
###vector  result.push_back(vector<int>{})或者  result.push_back({})
###vector  二维数组排序
static bool cmp(vector<int>&a,vector<int>&b){
        if(a[0]!=b[0])
            return a[0]<b[0];
        else   
            return a[1]<b[1];
    }
sort(intervals.begin(),intervals.end(),cmp);
 

回溯法去重,排序+if(nums[i]!=nums[i-1]),太好用了!

性能:本质是穷举,最多剪枝一下

可以解决的问题:排列,组合,切割,子集,棋盘

理解:N叉树

模板:

void back(){

  if()

    return;

  for(){

    back();

    撤销结果;

  }

}

77. 组合 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     vector<vector<int>> result;
 4     vector<int> path;
 5     void back(int n,int k,int index){
 6         if(path.size()==k){
 7             result.push_back(path);
 8             return ;
 9         }
10         for(int i=index;i<=n;i++){
11             path.push_back(i);
12             back(n,k,i+1);
13             path.pop_back();
14         }
15     }
16     vector<vector<int>> combine(int n, int k) {
17         back(n,k,1);
18         return result;
19     }
20 };
View Code

 216. 组合总和 III - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     vector<int>path;
 4     vector<vector<int>> result;
 5     void back(int k,int n,int start){
 6         if(n==0&&k==path.size()){
 7             result.push_back(path);
 8             return ;
 9         }
10         for(int i=start;i<=9;i++){
11             path.push_back(i);
12             n-=i;
13             back(k,n,i+1);
14             path.pop_back();
15             n+=i;
16         }
17     }
18     vector<vector<int>> combinationSum3(int k, int n) {
19         back(k,n,1);
20         return result;
21     }
22 };
View Code

 17. 电话号码的字母组合 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     string path;
 4     vector<string> result;
 5      unordered_map<char, string> map{
 6             {'0', ""}, {'1',""}, {'2', "abc"},
 7             {'3',"def"}, {'4',"ghi"}, {'5',"jkl"},
 8             {'6',"mno"}, {'7',"pqrs"},{'8',"tuv"},
 9             {'9',"wxyz"}
10     };  
11     void back(string digits,int i){
12         if(path.size()==digits.size()){
13             result.push_back(path);
14             return ;
15         }
16         for(int j=0;j<map[digits[i]].size();j++){
17             path.push_back(map[digits[i]][j]);
18             back(digits,i+1);
19             path.pop_back();
20         }
21     }
22     
23     vector<string> letterCombinations(string digits) {
24         if(digits.size()==0)
25             return result;
26         back(digits,0);
27         return result;
28     }
29 };
View Code

 39. 组合总和 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     int sum;
 4     vector<int> path;
 5     vector<vector<int>> result;
 6     void back(vector<int>& candidates, int target){
 7         if(sum>target)//没这个溢出啥的
 8             return;
 9         if(sum==target){//去重
10             int flag = 1;
11             vector<int> temp = path;
12             sort(temp.begin(),temp.end());
13             for(int i=0;i<result.size();i++){
14                 if(result[i]==temp)
15                     flag = 0;
16             }
17             if(flag)
18                 result.push_back(temp);
19             return ;
20         }
21         for(int i=0;i<candidates.size();i++){
22             sum+=candidates[i];
23             path.push_back(candidates[i]);
24             back(candidates,target);
25             sum-=candidates[i];
26             path.pop_back();
27         }
28     }
29     vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
30         back(candidates,target);
31         return result;
32     }
33 };
View Code
 1 class Solution {
 2 public:
 3     int sum;
 4     vector<int> path;
 5     vector<vector<int>> result;
 6     void back(vector<int>& candidates, int target,int startIndex){
 7         if(sum>target)//没这个溢出啥的
 8             return;
 9         if(sum==target){//
10             result.push_back(path);
11             return ;
12         }
13         for(int i=startIndex;i<candidates.size();i++){
14             sum+=candidates[i];
15             path.push_back(candidates[i]);
16             back(candidates,target,i);
17             sum-=candidates[i];
18             path.pop_back();
19         }
20     }
21     vector<vector<int>> combinationSum(vector<int>& candidates, int target) {//元素是否重复选取,就是startIndex是i还是i+1这么传递
22         back(candidates,target,0);
23         return result;
24     }
25 };
View Code

 40. 组合总和 II - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     vector<int> path;
 4     vector<vector<int>> result;
 5     int sum;
 6     void back(vector<int>& candidates, int target,int startIndex){
 7         if(sum == target){
 8             result.push_back(path);
 9             return ;
10         }
11         for(int i=startIndex;i<candidates.size()&&sum+candidates[i]<=target;i++){//这道题因为有重复元素,所以要去重了耶
12             if(i>startIndex&&candidates[i] == candidates[i-1])
13                 continue;
14             path.push_back(candidates[i]);
15             sum+=candidates[i];
16             back(candidates,target,i+1);
17             path.pop_back();
18             sum-=candidates[i];
19         }
20     }
21     vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
22         // 首先把给candidates排序,让其相同的元素都挨在一起。
23         sort(candidates.begin(), candidates.end());
24         back(candidates,target,0);
25         return result;
26     }
27 };
View Code

 131. 分割回文串 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     vector<string> path;
 4     vector<vector<string>> result;
 5     bool istrue(string &s,int start,int end){
 6         for(int i=start,j=end;i<j;i++,j--){
 7             if(s[i]!=s[j]){
 8                 return false;
 9             }
10         }
11         return true;
12     }
13     void back(string &s,int startIndex){
14         if(startIndex==s.size()){
15             result.push_back(path);
16             return;
17         }
18         for(int i=startIndex;i<s.size();i++){
19             if(istrue(s,startIndex,i)){
20                 string str = s.substr(startIndex,i-startIndex+1);
21                 path.push_back(str);
22                 back(s,i+1);
23                 path.pop_back();
24             }
25         }
26     }
27     vector<vector<string>> partition(string s) {
28         back(s,0);
29         return result ;
30     }
31 };
View Code

 93. 复原 IP 地址 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     vector<string>result;
 4     string path;
 5     void backtrace(string& s,int cnt,int startIndex){
 6         if(cnt==4 ){
 7             if(startIndex==s.size())
 8                 result.push_back(path);
 9             return ;
10         }     
11         for(int i=startIndex;i<s.size();i++){
12             int len = i-startIndex+1;
13             if(len>3)//超出范围剪枝
14                 return ;
15             if(s[startIndex]=='0' && i!=startIndex) //不合法IP地址有前缀0
16                 return;
17             if(len==3 && s.substr(startIndex,len)>"255") //不合法IP地址过大,字符串比较太精髓了
18                 return;
19             path+=s.substr(startIndex,len);
20             if(cnt!=3)
21                 path.push_back('.'); 
22             backtrace(s,cnt+1,i+1);
23             path = path.substr(0,path.size()-len);
24             if(cnt!=3)
25                 path = path.substr(0,path.size()-1);
26         }
27     }
28     vector<string> restoreIpAddresses(string s) { 
29         backtrace(s,0,0);
30         return result;
31     }
32 };
View Code

 78. 子集 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     vector<vector<int>> result;
 4     vector<int> path;
 5     void back(vector<int>& nums,int startIndex){
 6         result.push_back(path);
 7         if(startIndex==nums.size()){
 8             return ;
 9         }
10         for(int i=startIndex;i<nums.size();i++){
11             path.push_back(nums[i]);
12             back(nums,i+1);
13             path.pop_back();
14         }
15     }
16     vector<vector<int>> subsets(vector<int>& nums) {
17         back(nums,0);
18         return result;
19     }
20 };
View Code

 90. 子集 II - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     vector<int> path;
 4     vector<vector<int>> result;
 5     void back(vector<int>& nums,int startIndex){
 6         result.push_back(path);
 7         if(startIndex==nums.size()){
 8             return ;
 9         }
10         for(int i=startIndex;i<nums.size();i++){
11             if(i>startIndex&&nums[i]==nums[i-1]){
12                 continue ;
13             }
14             path.push_back(nums[i]);
15             back(nums,i+1);
16             path.pop_back();
17         }
18     }
19     vector<vector<int>> subsetsWithDup(vector<int>& nums) {
20         sort(nums.begin(),nums.end());
21         back(nums,0);
22         return result;
23     }
24 };
View Code

 491. 递增子序列 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     vector<int> path;
 4     vector<vector<int>> result;
 5     void back(vector<int>& nums,int startIndex){//[1,2,3,1,1,1] 去重完犊子了,这个不能排序哈哈哈,所以不能nums[i]==nums[i-1]这样了,
 6         if(path.size()>=2){
 7             result.push_back(path);
 8         }
 9         unordered_set<int> uset; // 使用set对本层元素进行去重
10         for(int i=startIndex;i<nums.size();i++){
11             if(path.size()!=0&&nums[i]<path.back())//递增
12                 continue ;
13             if(uset.find(nums[i]) != uset.end())//去重
14                 continue ;
15             uset.insert(nums[i]);
16             path.push_back(nums[i]);
17             back(nums,i+1);
18             path.pop_back();
19         }
20     }
21 
22     vector<vector<int>> findSubsequences(vector<int>& nums) {
23         back(nums,0);
24         return result;
25     }
26 };
View Code

 46. 全排列 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     vector<int> path;
 4     vector<vector<int>> result;
 5     void back(vector<int>& nums,vector<bool>&used){
 6         if(path.size() == nums.size()){
 7             result.push_back(path);
 8             return ;
 9         }
10         for(int i=0;i<nums.size();i++){
11             if(used[i])
12                 continue ;
13             used[i] = true;
14             path.push_back(nums[i]);
15             back(nums,used);
16             used[i] = false;
17             path.pop_back();
18         }
19     }
20     vector<vector<int>> permute(vector<int>& nums) {
21         vector<bool>used(nums.size(),false);
22         back(nums,used);
23         return result;
24     }
25 };
View Code

 51. N 皇后 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     vector<vector<string>> result;
 4     bool isValid(int n,int row,int col,vector<string> path){
 5         for(int i=0;i<row;i++){//
 6             if(path[i][col]=='Q')
 7                 return false;
 8         }
 9         for(int i=row-1,j=col-1;i>=0&&j>=0;i--,j--){//45度往左上
10             if(path[i][j]=='Q')
11                 return false;
12         }
13         for(int i=row-1,j=col+1;i>=0&&j<n;i--,j++){//45度往左上
14             if(path[i][j]=='Q')
15                 return false;
16         }
17         return true;
18     }
19     void back(int n,int num,vector<string>& path){
20         if(num == n){
21             result.push_back(path);
22             return ;
23         }
24         for(int col=0;col<n;col++){//
25             if(!isValid(n,num,col,path))
26                 continue ;
27             path[num][col] = 'Q';
28             back(n,num+1,path);
29             path[num][col] = '.';
30         }
31     }
32     vector<vector<string>> solveNQueens(int n) {
33         vector<string> path(n, string(n, '.'));//初始化n行n列都为.
34         back(n,0,path);
35         return result;
36     }
37 };
View Code

 37. 解数独 - 力扣(LeetCode) (leetcode-cn.com)

 1 class Solution {
 2 public:
 3     bool isValid(int row, int col, char val, vector<vector<char>>& board) {
 4     for (int i = 0; i < 9; i++) { // 判断行里是否重复
 5         if (board[row][i] == val) {
 6             return false;
 7         }
 8     }
 9     for (int j = 0; j < 9; j++) { // 判断列里是否重复
10         if (board[j][col] == val) {
11             return false;
12         }
13     }
14     int startRow = (row / 3) * 3;//这里求九方格起始位置也很巧
15     int startCol = (col / 3) * 3;
16     for (int i = startRow; i < startRow + 3; i++) { // 判断9方格里是否重复
17         for (int j = startCol; j < startCol + 3; j++) {
18             if (board[i][j] == val ) {//判断的是当前加入进去的数有没有和之前的数冲突,初始数独肯定有效。所以不要判断每个数不超过1次
19                 return false;
20             }
21         }
22     }
23     return true;
24     }
25     bool back(vector<vector<char>>& board){
26         for(int i=0;i<9;i++){
27             for(int j=0;j<9;j++){
28                 if(board[i][j]!='.')
29                     continue;
30                 for(char k='1';k<='9';k++){
31                     if(isValid(i,j,k,board)){
32                         board[i][j] = k;
33                         back(board)//只有一种解,所以找到了就不用回溯,主要是结果是board,不是自定义的
34                         board[i][j] = '.';
35                     }
36                 }
37             }
38         }
39         return true;//没有i,j循环完了,棋盘遍历完了,答案出来了。
40     }
41     void solveSudoku(vector<vector<char>>& board) {
42         back(board);
43     }
44 };
View Code

 

posted @ 2022-01-30 14:53  剩下的交给时间就好  阅读(139)  评论(0编辑  收藏  举报