77.Combinations
思路:终止和收敛条件是判断out中的个数达到k。图解请详见博客题解。
vector<vector<int>> combine(int n, int k) {
vector<int> out;
vector<vector<int>> res;
if (k < 1 || n < 1 || n < k)
return res;
DFS(n,k,out,res,1);
return res;
}
void DFS(int n,int k,vector<int>& out,vector<vector<int>>& res,int start) {
if (out.size() == k) {
res.push_back(out);
}
else {
for (int i = start; i <= n; i++) {
out.push_back(i);
DFS(n,k,out,res,i+1);
out.pop_back();
}
}
}
78.SubsetsSubsets
思路:用到DFS,但是和以往只需要保存叶子节点数据不同,这个需要把路径上所有节点都保存。可能是最新题,竟然是最快的一种。。。。。
vector<vector<int>> subsets(vector<int>& nums) {
vector<int> out;
vector<vector<int>> res;
res.push_back(out);
DFS(nums,res,out,0);
return res;
}
void DFS(vector<int>& nums,vector<vector<int>>& res,vector<int>& out,int start) {
for (int i = start; i < nums.size(); i++) {
out.push_back(nums[i]);
res.push_back(out);
DFS(nums,res,out,i+1);
out.pop_back();
}
}
89.Gray Code
思路1:百度一下二进制数——>格雷码的转换,就知道怎么做了。就是一个数n的每一位和上一位进行异或运算。
vector<int> grayCode(int n) {
// 这道题如果用二进制转换成格雷码,只要知道转换规则,很容易Gi = Bi xor Bi+1
vector<int> res;
for (int i = 0; i < pow(2,n); i++) {
res.push_back((i>>1) ^ i);
}
return res;
}
思路2:但是如果不知道怎么办,怎么用回溯法呢。
93.Restore IP Addresses
思路:必须走到底才能知道是不是符合要求,用DFS。
vector<string> restoreIpAddresses(string s) {
vector<string> out;
vector<string> res;
DFS(s,0,out,res);
return res;
}
void DFS(string s,int start,vector<string>& out,vector<string>& res) {
if (start == s.size() && out.size() == 4) {
string ip = out[0] + "." + out[1] +"." + out[2] + "." + out[3];
res.push_back(ip);
return;
}
if (s.size() - start > (4 - out.size()) * 3 || s.size() - start < (4 - out.size())) {
return;
}
for (int i = start; i < start + 3 && i < s.size(); i++) {
string temp = s.substr(start,i - start + 1);
if (isValid(temp)) {
out.push_back(temp);
DFS(s,i + 1,out,res);
out.pop_back();
}
}
}
bool isValid(string s) {
int num = stoi(s);
if (num < 0 || num > 255)
return false;
if (s[0] == '0')
return s.size() == 1;
return true;
}
216.Combination Sum III
思路:
vector<vector<int>> combinationSum3(int k, int n) {
vector<int> input = {1,2,3,4,5,6,7,8,9};
vector<int> out;
vector<vector<int>> res;
DFS(k,n,0,0,input,out,res);
return res;
}
void DFS(int k,int n,int level,int start,vector<int>& input,vector<int>& out,vector<vector<int>>& res) {
if (level == k) {
if (accumulate(out.begin(),out.end(),0) == n)
res.push_back(out);
else
return;
}
else {
for (int i = start; i < input.size(); i++) {
out.push_back(input[i]);
DFS(k,n,level+1,i+1,input,out,res);
out.pop_back();
}
}
}
解法2:
vector<vector<int>> combinationSum3(int k, int n) {
//vector<int> input = {1,2,3,4,5,6,7,8,9};
vector<int> out;
vector<vector<int>> res;
DFS(k,n,1,out,res);
return res;
}
void DFS(int k,int n,int start,vector<int>& out,vector<vector<int>>& res) {
if (out.size() == k) {
if (n == 0)
res.push_back(out);
else
return;
}
if (out.size() < k) {
for (int i = start; i <= 9;i++) {
out.push_back(i);
DFS(k,n - i,i+1,out,res);
out.pop_back();
}
}
}
- Subsets II
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(),nums.end());
vector<int> out;
vector<vector<int>> res;
res.push_back(out);
DFS(nums,res,out,0);
return res;
}
void DFS(vector<int>& nums,vector<vector<int>>& res,vector<int>& out,int start) {
for (int i = start; i < nums.size();i++) {
if (i > start && nums[i] == nums[i-1])
continue;
out.push_back(nums[i]);
res.push_back(out);
DFS(nums,res,out,i+1);
out.pop_back();
}
}
- Palindrome Partitioning
思路:
vector<vector<string>> partition(string s) {
vector<vector<string>> res;
vector<string> out;
DFS(s,out,res,0);
return res;
}
void DFS(string& s,vector<string>& out,vector<vector<string>>& res,int start) {
if (start == s.size())
res.push_back(out);
for (int i = start; i < s.size(); i++) {
string temp = s.substr(start,i-start+1);
if (isValid(temp)) {
out.push_back(temp);
DFS(s,out,res,i+1);
out.pop_back();
}
}
}
bool isValid(string s) {
if (s.empty())
return false;
int start = 0,end = s.size() - 1;
while (start < end && s[start] == s[end]) {
start++;
end--;
}
if (start >= end)
return true;
return false;
}
- Letter Case Permutation
思路1:不用DFS,我们关心的是字母,数字的处理很简单,直接加上就可以了。比如说S = “abc”,那么先让 res = [“”],然后res中的每个字符串分别加上第一个字符a和A,得到 [“a”, “A”],然后res中的每个字符串分别加上第二个字符b和B,得到 [“ab”, “Ab”, “aB”, “AB”],然后res中的每个字符串分别加上第三个字符c和C,得到 [“abc”, “Abc”, “aBc”, “ABc”, “abC”, “AbC”, “aBC”, “ABC”]
vector<string> letterCasePermutation(string S) {
vector<string> res{""};
for (char c : S) {
int len = res.size();
if (c >= '0' && c <= '9') { //如果是数字,res中每个string加就可以
for (int i = 0; i < len; i++) {
res[i] += c;
}
}
else { //如果是字母,则进行大小写相加
for (int i = 0; i < len; i++) {
res.push_back(res[i]);
res[i] += tolower(c);
res[len+i] += toupper(c);
}
}
}
return res;
}
- Beautiful Arrangement
思路:
int countArrangement(int N) {
int count = 0;
vector<bool> visited(N,false);
DFS(N,1,visited,count);
return count;
}
void DFS(int N,int pos,vector<bool>& visited,int& count) {
if (pos > N)
count++;
for (int i = 1; i <= N; i++) {
if (!visited[i-1] && isValid(i,pos)) {
visited[i-1] = true;
DFS(N,pos+1,visited,count);
visited[i-1] = false;
}
}
}
bool isValid(int n,int pos) {
if (n % pos == 0 || pos % n == 0)
return true;
return false;
}
- N-Queens
思路:终于遇到了经典的N皇后问题,典型的回溯。
vector<vector<string>> solveNQueens(int n) {
vector<int> C(n,-1);
vector<vector<string>> res;
DFS(C,res,0);
return res;
}
void DFS(vector<int>& C,vector<vector<string>>& res,int row) {
int n = C.size();
if (row == n) {
vector<string> out;
for (int i = 0; i < n; i++) {
string temp(n,'.');
temp[C[i]] = 'Q';
out.push_back(temp);
}
res.push_back(out);
}
for (int j = 0; j < n; j++) {
if (isValid(C,row,j)) {
C[row] = j;
DFS(C,res,row+1);
C[row] = -1;
}
}
}
bool isValid(vector<int> C,int row,int col) {
for(int i = 0; i < row; i++) {
if (C[i] == col || abs(row-i) == abs(col-C[i]))
return false;
}
return true;
}
- N-Queens II
int totalNQueens(int n) {
vector<int> C(n,-1);
int count = 0;
DFS(C,count,0);
return count;
}
void DFS(vector<int>& C,int& count,int row) {
int n = C.size();
if (row == n) {
count++;
}
for (int j = 0; j < n; j++) {
if (isValid(C,row,j)) {
C[row] = j;
DFS(C,count,row+1);
C[row] = -1;
}
}
}
bool isValid(vector<int> C,int row,int col) {
for (int i = 0; i < row; i++) {
if (C[i] == col || abs(row - i) == abs(col - C[i]))
return false;
}
return true;
}