#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;
}