代码随想录-回溯算法

发布于 2022年 05月 19日 10:29

#include <iostream>
#include <vector>
#include <string>
#include <unordered_set>
#include <unordered_map>
#include <map>

using namespace std;

template<typename T>
void print(const vector<T>& nums)
{
    for(auto&& num : nums)
    {
        cout << num << " ";
    }
    cout << endl;
    cout << "=====" << endl;
}

template<typename T>
void print(const vector<vector<T>>& vecs)
{
    for(const vector<T>& nums : vecs)
    {
        for(auto num : nums)
        {
            cout << num << " ";
        }
        cout << endl;
    }
    cout << "=====" << endl;
}

void backtrack(int n, int k, vector<int>&path,vector<vector<int>>&res, int index)
{    
    if(path.size() == k)
    {
        res.push_back(path);                        
        return;
    }
    for(int i = index; i <= n; ++i)
    {
        path.push_back(i);
        backtrack(n,k,path,res,i + 1);
        path.pop_back();
    }
}

void backtrack_jianzhi(int n, int k, vector<int>&path,vector<vector<int>>&res, int index)
{    
    if(path.size() == k)
    {
        res.push_back(path);                        
        return;
    }
    for(int i = index; i <= n - (k - path.size()) + 1; ++i)
    {
        path.push_back(i);
        backtrack_jianzhi(n,k,path,res,i + 1);
        path.pop_back();
    }
}

vector<vector<int>>combine(int n, int k)
{
    vector<vector<int>>res;
    vector<int>path;
    // backtrack(n,k,path,res,1);    
    backtrack_jianzhi(n,k,path,res,1);    
    return res;
}

void backtrack(int n, int k, vector<int>&path,vector<vector<int>>&res,int sum, int index)
{
    if(path.size() == k)
    {
        if(sum == n)
        {
            res.push_back(path);
        }
        return ;
    }
    for(int i = index; i <= 9; ++i)
    {
        path.push_back(i);
        sum += i;
        backtrack(n,k,path,res,sum,i + 1);
        sum -= i;
        path.pop_back();
    }
    return;
}

void backtrack_jianzhi(int n, int k, vector<int>&path,vector<vector<int>>&res,int sum, int index)
{
    if(sum > n)return;
    if(path.size() == k)
    {
        if(sum == n)
        {
            res.push_back(path);
        }
        return ;
    }
    for(int i = index; i <= 9 - (path.size() - k) + 1; ++i)
    {
        path.push_back(i);
        sum += i;
        backtrack_jianzhi(n,k,path,res,sum,i + 1);
        sum -= i;
        path.pop_back();
    }
    return;
}


vector<vector<int>>combinationSum3(int n, int k)
{
    vector<vector<int>>res;
    vector<int>path;
    backtrack_jianzhi(n,k,path,res,0,1);
    // backtrack(n,k,path,res,0,1);
    return res;
}

string letterMap[10]={
    "",
    "",
    "abc",
    "def",
    "ghi",
    "jkl",
    "mno",
    "pqrs",
    "tuv",
    "wxyz"};

void backtrack(const string & digits, string& s, vector<string>& res,int index)
{
    if(s.size() == digits.size())
    {
        res.push_back(s);
        return;
    }
    int digit = digits[index] - '0';
    string letter = letterMap[digit];
    for(int i = 0; i < letter.size(); ++i)
    {
        s.push_back(letter[i]);
        backtrack(digits,s,res,index + 1);
        s.pop_back();
    }
}

vector<string> letterCombinations(const string& digits)
{
    vector<string>res;
    if(digits.size() == 0)return res;
    string s;
    backtrack(digits,s,res,0);
    return res;
}

void backtrackI(const vector<int>& candidates,int target,vector<int>&path,vector<vector<int>>&res,int sum, int index)
{
    if(sum > target)return;
    if(sum == target)
    {
        res.push_back(path);
        return;
    }
    for(int i = index ; i < candidates.size(); ++i)
    {
        sum += candidates[i];
        path.push_back(candidates[i]);
        backtrackI(candidates,target,path,res,sum,i);
        path.pop_back();
        sum -= candidates[i];
    }

}

vector<vector<int>>combinationSum(const vector<int>& candidates, int target)
{
    vector<vector<int>>res;
    vector<int>path;
    backtrackI(candidates,target,path,res,0,0);
    return res;
}

void backtrack(const vector<int>&candidiates,vector<int>&path,vector<vector<int>>&res,int \
target,int sum,int index,vector<bool>&used)
{
    if(sum == target)
    {
        res.push_back(path);
        return;
    }    
    for(int i = index; i < candidiates.size() && sum + candidiates[i] <= target ; ++i)
    {
        if(i > 0 && candidiates[i] == candidiates[i-1] && used[i-1] == false)
        {
            continue;
        }
        path.push_back(candidiates[i]);
        sum += candidiates[i];
        used[i] = true;
        backtrack(candidiates,path,res,target,sum,i+1,used);
        used[i] = false;
        sum -= candidiates[i];
        path.pop_back();
    }
}

vector<vector<int>>combinationSum2(vector<int>&candidates,int target)
{
    vector<bool>used(candidates.size(),false);
    vector<int>path;
    vector<vector<int>>res;
    sort(candidates.begin(),candidates.end());
    backtrack(candidates,path,res,target,0,0,used);
    return res;

}

bool isHuiWen(string s, int left,int right)
{
    for(int i = left,j = right ; i < j; ++i,--j)
    {
        if(s[i] != s[j])return false;
    }
    return true;
}

void backtrack(string s, int index, vector<vector<string>>&res,vector<string>&path)
{
    if(index >= s.size())
    {
        res.push_back(path);
        return ;
    }
    for(int i = index; i < s.size(); ++i)
    {
        if(isHuiWen(s,index,i))
        {
            string str = s.substr(index,i - index + 1);
            path.push_back(str);
        }
        else{
            continue;
        }
        backtrack(s,i + 1,res,path);
        path.pop_back();
    }
}

vector<vector<string>>partition(string s)
{
    vector<vector<string>>res;
    vector<string>path;
    backtrack(s,0,res,path);
    return res;

}

bool isValid(const string s,int start,int end)
{
    if(start > end)return false;
    if(s[start] == '0' && start != end)
    {
        return false;
    }
    int num = 0;
    for(int i = start; i <= end; ++i)
    {
        if(s[i] < '0' || s[i] > '9')return false;
        num = 10 * num + s[i] - '0';
        if(num > 255)
        {
            return false;
        }
    }    
    return true;    
}

void backtrack(string& s, string& path,vector<string>&res,int index,int pointnum)
{
    if(pointnum == 3)
    {
        if(isValid(s,index,s.size() - 1))
        {
            res.push_back(s);
        }
        return;
    }
    for(int i = index;i < s.size(); ++i)
    {
        if(isValid(s,index,i))
        {
            s.insert(s.begin() + i + 1,'.');
            ++pointnum;
            backtrack(s,path,res,i + 2, pointnum);
            --pointnum;
            s.erase(s.begin() + i + 1);
        }
    }


}

vector<string> restoreIPaddreses(string s)
{
    vector<string>res;
    string path;
    backtrack(s,path,res,0,0);
    return res;

}

void backtrack_sub(const vector<int>& nums,vector<vector<int>>&res,vector<int>&path,int index)
{
    res.push_back(path);
    if(index >= nums.size())
    {
        return;
    }
    for(int i = index; i < nums.size(); ++i)
    {
        path.push_back(nums[i]);
        backtrack_sub(nums,res,path,i+1);
        path.pop_back();
    }
}

vector<vector<int>>subset(const vector<int>& nums)
{
    vector<vector<int>>res;
    vector<int>path;
    backtrack_sub(nums,res,path,0);
    return res;
}

void backtrack_sequence(const vector<int>& nums,vector<int>path,vector<vector<int>>&res,int index)
{
    if(path.size() > 1)
    {
        res.push_back(path);
    }
    unordered_set<int>set;
    for(int i = index; i < nums.size();++i)
    {
        if((!path.empty() && nums[i] < path.back()) || set.find(nums[i])!=set.end())continue;
        set.insert(nums[i]);
        path.push_back(nums[i]);
        backtrack_sequence(nums,path,res,i + 1);
        path.pop_back();
    }
}

vector<vector<int>>findSubSquences(const vector<int>& nums)
{
    vector<int>path;
    vector<vector<int>>res;
    backtrack_sequence(nums,path,res,0);
    return res;
}

void backtrack(const vector<int>& nums,vector<int>&path,vector<vector<int>>&res,vector<bool>&used)
{
    if(path.size() == nums.size())
    {
        res.push_back(path);
        return;
    }
    for(int i = 0; i < nums.size(); ++i)
    {
        if(used[i])continue;
        path.push_back(nums[i]);
        used[i] = true;
        backtrack(nums,path,res,used);
        used[i] = false;
        path.pop_back();
    }
}

vector<vector<int>>permute(const vector<int>& nums)
{
    vector<vector<int>>res;
    vector<int>path;
    vector<bool>used(nums.size(),false);
    backtrack(nums,path,res,used);
    return res;
}

void backtrack_permute(const vector<int>&nums,vector<int>&path,vector<vector<int>>&res,vector<bool>&used)
{
    if(path.size() == nums.size())
    {
        res.push_back(path);        
        return;
    }
    
    for(int i = 0; i < nums.size(); ++i)
    {
        if(i > 0 && nums[i] == nums[i-1] && used[i-1]== false)continue;
        if(used[i] == false)
        {
            path.push_back(nums[i]);
            used[i] = true;
            backtrack_permute(nums,path,res,used);
            used[i] = false;
            path.pop_back();
        }        
    }        
}

vector<vector<int>>permuteII(const vector<int>& nums)
{
    vector<vector<int>>res;
    vector<int>path;
    vector<bool>used(nums.size(),false);
    backtrack_permute(nums,path,res,used);
    return res;
}

void backtrack_subset(const vector<int>& nums,vector<int>&path,vector<vector<int>>&res,vector<bool>&used,int index)
{
    res.push_back(path);
    unordered_set<int>set;
    for(int i = index; i < nums.size(); ++i)
    {
        if(set.find(nums[i]) != set.end())continue;
        set.insert(nums[i]);
        path.push_back(nums[i]);
        backtrack_subset(nums,path,res,used,i + 1);
        path.pop_back();
    }
}

vector<vector<int>>subsetII(const vector<int>& nums)
{
    vector<vector<int>>res;
    vector<int>path;
    vector<bool>used(nums.size(),false);
    backtrack_subset(nums,path,res,used,0);
    return res;
}

bool isValid(int row,int col,vector<string>&chessboard,int n)
{
    for(int i = 0; i < row; ++i)
    {
        if(chessboard[i][col] == 'Q')
        return false;
    }
    for(int i = row - 1,j = col - 1; i >= 0 && j >= 0; --i,--j)
    {
        if(chessboard[i][j] == 'Q')
        return false;
    }
    for(int i = row - 1,j = col + 1; i >= 0 && j < n; --i,++j)
    {
        if(chessboard[i][j] == 'Q')
        return false;
    }
    return true;
}

void backtrack_help(vector<string>&chessboard,vector<vector<string>>&res,int row,int n)
{
    if(row == n)
    {
        res.push_back(chessboard);
        return;        
    }
    for(int col = 0; col < n; ++col)
    {
        if(isValid(row,col,chessboard,n))
        {
            chessboard[row][col] = 'Q';
            backtrack_help(chessboard,res,row+1,n);
            chessboard[row][col] = '.';
        }
    }
}

vector<vector<string>>solveNqueens(int n)
{
    vector<vector<string>>res;
    vector<string>chessboard(n,string(n,'.'));
    backtrack_help(chessboard,res,0,n);
    return res;

}

bool isValid_sudoku(int row,int col,const vector<string>&board,char k)
{
    for(int i = 0; i < 9; ++i)
    {
        if(board[i][col] == k)return false;
    }
    for(int j = 0; j < 9; ++j)
    {
        if(board[row][j] == k)return false;        
    }
    int startRow = (row / 3) * 3;
    int startCol = (col / 3) * 3;
    for(int i = startRow; i < startRow + 3; ++i)
    {
        for(int j = startCol; j < startCol + 3; ++j)
        {
            if(board[i][j] == k)return false;
        }
    }
    return true;
}

bool backtrack_sudoku(vector<string>&board)
{
    int m = board.size(), n = board[0].size();
    for(int i = 0; i < m; ++i)
    {
        for(int j = 0; j < n; ++j)
        {
            if(board[i][j]!='.')continue;
            for(char k = '1'; k <= '9'; ++k)
            {
                if(isValid_sudoku(i,j,board,k))
                {
                    board[i][j] = k;
                    if(backtrack_sudoku(board))return true;
                    board[i][j] = '.';
                }
            }
            return false;
        }
    }
    return true;
}

vector<string> solveSudoku(vector<string>&board)
{

    backtrack_sudoku(board);
    return board;
}

bool backtrack(unordered_map<string,map<string,int>>&targets,vector<string>& res,int ticketNum)
{
    if(res.size() == ticketNum + 1)
    {
        return true;
    }
    for(pair<const string,int>&target:targets[res[res.size() - 1]])
    {
        if(target.second > 0)
        {
            res.push_back(target.first);
            --target.second;
            if(backtrack(targets,res,ticketNum))return true;
            ++target.second;
            res.pop_back();
        }
    }
    return false;
}

vector<string>findItinerary(vector<vector<string>>&tickets)
{
    vector<string>res;
    unordered_map<string,map<string,int>>target;
    for(const auto& ticket:tickets)
    {
        ++target[ticket[0]][ticket[1]];
    }
    res.push_back("JFK");
    backtrack(target,res,target.size());
    return res;

    
}

int main()
{
    
    //LeetCode77:组合
    int n = 4, k = 2;
    print(combine(n,k));

    //LeetCode216 组合总和III(不重复)
    k = 3, n = 7;
    print(combinationSum3(n,k));

    //LeetCode17 电话号码的字母组合
    print(letterCombinations("23"));

    //LeetCode39 组合总和(可重复)
    vector<int>candidates{2,3,6,7};
    int target = 7;
    print(combinationSum(candidates,target));

    //LeetCode40 组合总和II(每个数字在每个组合中只能使用一次)
    candidates = {2,5,2,1,2};
    target = 5;
    print(combinationSum2(candidates,target));

    //LeetCode131分割回文串
    string s = "aab";
    print<string>(partition(s));

    //LeetCode93复原所有IP地址
    print<string>(restoreIPaddreses("25525511135"));

    //LeetCode78 子集
    vector<int>nums{1,2,3};
    print(subset(nums));

    //LeetCode90 子集II
    nums = {1,2,2};
    print(subsetII(nums));


    //LeetCode491 递增子序列
    nums = {4,6,7,7};
    print(findSubSquences(nums));

    //LeetCode46 全排列
    nums = {1,2,3};
    print(permute(nums));

    //LeetCode47 全排列II
    nums = {1,1,2};
    print(permuteII(nums));

    //LeetCode332 重新安排行程
    vector<vector<string>>tickets{{"MUC","LHR"},{"JFK","MUC"},{"SFO","SJC"},{"LHR","SFO"}};
    print(findItinerary(tickets));


    //LeetCode51 N皇后
    print<string>(solveNqueens(4));

    //LeetCode37 解数独
    vector<string>board{
        "53..7....",
        "6..195...",
        ".98....6.",        
        "8...6...3",    
        "4..8.3..1",
        "7...2...6",
        ".6....28.",
        "...419..5",
        "....8..79"
    };
    print<string>(solveSudoku(board));

    return 0;
}

 

推荐文章