回溯法:又称为试探法,即当探索到某一步时,发现原先的选择达不到目的,就退回一步重新选择。
78.子集
<1>回溯法
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
vector<int> item;
vector<vector<int>> res;
res.push_back(item);
generate(0,nums,item,res);
return res;
}
void generate(int i, vector<int>& nums, vector<int>& item, vector<vector<int>>& res){
if(i>=nums.size())
return;
item.push_back(nums[i]);
res.push_back(item);
generate(i+1, nums, item, res);
item.pop_back();
generate(i+1, nums, item, res);
}
};
<2>位运算
class Solution {
public:
vector<vector<int>> subsets(vector<int>& nums) {
int all_set = 1 << nums.size();
vector<vector<int>> res;
for(int i = 0; i < all_set; ++i){
vector<int> item;
for(int j = 0; j < nums.size(); ++j){
if((1<<j)&i){
item.push_back(nums[j]);
}
}
res.push_back(item);
}
return res;
}
};
90.子集II
排序,set去重
class Solution {
public:
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<vector<int>> res;
set<vector<int>> res_set;
int all_set = 1 << nums.size();
sort(nums.begin(), nums.end());
for(int i = 0; i < all_set; ++i){
vector<int> item;
for(int j = 0; j < nums.size(); ++j){
if(i&(1<<j))
item.push_back(nums[j]);
}
if(res_set.find(item)==res_set.end()){
res_set.insert(item);
res.push_back(item);
}
}
return res;
}
};
40.组合总和II
在回溯过程中进行剪枝操作
class Solution {
public:
vector<vector<int>> combinationSum2(vector<int>& candidates, int target) {
sort(candidates.begin(), candidates.end());
vector<vector<int>> res;
set<vector<int>> res_set;
vector<int> item;
generate(0, candidates, item, res, res_set, 0, target);
return res;
}
void generate(int i, vector<int>& candidates, vector<int>& item, vector<vector<int>>& res, set<vector<int>>& res_set, int sum, int target){
if(i>=candidates.size() || sum > target) return;
sum += candidates[i];
item.push_back(candidates[i]);
if(sum==target && res_set.find(item)==res_set.end()){
res_set.insert(item);
res.push_back(item);
}
generate(i+1, candidates, item, res, res_set, sum, target);
sum -= candidates[i];
item.pop_back();
generate(i+1, candidates, item, res, res_set, sum, target);
}
};
22.括号生成
class Solution {
public:
vector<string> generateParenthesis(int n) {
vector<string> res;
generate("", n, n, res);
return res;
}
void generate(string item, int left, int right, vector<string>& res){
if(left==0&&right==0){
res.push_back(item);
return;
}
if(left > 0){
generate(item+"(", left-1, right,res);
}
if(left < right){
generate(item+")", left, right-1, res);
}
}
};
51.N皇后
回溯法
class Solution {
public:
vector<vector<string>> solveNQueens(int n) {
vector<vector<string>> res;
vector<string> loc;
vector<vector<int>> mark;
for(int i = 0; i < n; ++i){
mark.push_back(vector<int>(n,0));
loc.push_back(string(n,'.'));
}
generate(0, n, mark, loc, res);
return res;
}
void generate(int k, int n, vector<vector<int>>& mark, vector<string>& loc, vector<vector<string>>& res){
if(k==n){
res.push_back(loc);
return;
}
for(int i = 0; i < n; ++i){
if(mark[k][i]==0){
vector<vector<int>> tmp_mark = mark;
loc[k][i] = 'Q';
put_down_queen(k,i,mark);
generate(k+1, n, mark, loc, res);
mark = tmp_mark;
loc[k][i] = '.';
}
}
}
void put_down_queen(int x, int y, vector<vector<int>>& mark){
static const int dx[] = {
-1,1,0,0,-1,-1,1,1};
static const int dy[] = {
0,0,-1,1,-1,1,-1,1};
for(int i = 1; i < mark.size(); ++i){
for(int j = 0; j < 8; ++j){
int new_x = x + i*dx[j];
int new_y = y + i*dy[j];
if(new_x >= 0 && new_y >= 0 && new_x <mark.size() && new_y < mark.size()){
mark[new_x][new_y] = 1;
}
}
}
}
};
分治算法:将一个规模为N的问题分解为K个规模较小的子问题,而且这些子问题相互独立且与原问题性质相同。求出子问题的解后进行合并,就可以得到原问题的解。
315.计算右侧小于当前元素的个数
class Solution {
public:
vector<int> countSmaller(vector<int>& nums) {
vector<pair<int,int>> vec;
vector<int> count;
for(int i = 0; i < nums.size(); ++i){
vec.push_back(make_pair(nums[i], i));
count.push_back(0);
}
merge_sort(vec,count);
return count;
}
void merge_sort(vector<pair<int,int>>& vec, vector<int>& count){
if(vec.size() < 2) return;
int mid = vec.size()/2;
vector<pair<int,int>> sub_vec1;
vector<pair<int,int>> sub_vec2;
for(int i = 0; i < mid; ++i){
sub_vec1.push_back(vec[i]);
}
for(int i = mid; i < vec.size(); ++i){
sub_vec2.push_back(vec[i]);
}
merge_sort(sub_vec1,count);
merge_sort(sub_vec2,count);
vec.clear();
merge_sort_two_vec(sub_vec1,sub_vec2,vec,count);
}
void merge_sort_two_vec(vector<pair<int,int>>& sub_vec1, vector<pair<int,int>>& sub_vec2, vector<pair<int,int>>& vec, vector<int>& count){
int i = 0, j = 0;
while(i < sub_vec1.size() && j < sub_vec2.size()){
if(sub_vec1[i].first <= sub_vec2[j].first){
count[sub_vec1[i].second] += j;
vec.push_back(sub_vec1[i]);
i++;
}else{
vec.push_back(sub_vec2[j]);
j++;
}
}
for(; i < sub_vec1.size(); ++i){
count[sub_vec1[i].second] += j;
vec.push_back(sub_vec1[i]);
}
for(; j < sub_vec2.size(); ++j){
vec.push_back(sub_vec2[j]);
}
}
};