leetcode_04 递归,回溯与分治
一.递归
递归调用实现数字 1+2+3。。。
#include<iostream>
void compute_sum(int i,int &sum)
{
if(i>3)
{return;}
sum=sum+i;
compute_sum(i+1,sum);
}
int main()
{
int sum=0;
compute_sum(1,sum);
printf("sum=%d\n",sum);
return 0;
}
递归将链表放入数组中
#include<iostream>
#include<vector>
using namespace std;
struct ListNode
{
int val;
ListNode *next;
ListNode(int x):val(x),next(NULL){}
};
void add_to_vector(ListNode *head,vector<int>&vec)
{
if(!head)
return;
vec.push_back(head->val);
add_to_vector(head->next,vec);
}
int main()
{
ListNode a(1);
ListNode b(2);
ListNode c(3);
ListNode d(4);
ListNode e(5);
a.next=&b;
b.next=&c;
c.next=&d;
d.next=&e;
vector<int>vec;
add_to_vector(&a,vec);
for(int i=0;i<vec.size();i++)
{
printf("[%d]",vec[i]);
}
printf("\n");
return 0;
}
二.回溯
回溯法又称试探法,但当探索到某一步的时候,发现原先选择达不到目标,就退一步重新选择,这种走不通就退回再走的技术为回溯法。
例1.子集
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例 1:
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
示例 2:
输入:nums = [0]
输出:[[],[0]]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/subsets
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
第一步:设置输出各个子集
#include<stdio.h>
#include<vector>
using namespace std;
int main()
{
vector<int>nums;
nums.push_back(1);
nums.push_back(2);
nums.push_back(3);
vector<int>item;//生成各个子集的数组
vector<vector<int>>result;//生成最终的结果数组
for(int i=0;i<nums.size();i++)
{
item.push_back(nums[i]);
result.push_back(item);
}
for(int i=0;i<result.size();i++)
{
for(int j=0;j<result[i].size();j++)
{
printf("[%d].",result[i][j]);
}
printf("\n");
}
return 0;
}
第一步:递归输出各个子集
#include<stdio.h>
#include<vector>
using namespace std;
void generate(int i,vector<int>& nums,vector<int>&item,vector<vector<int>>&result)
{
if(i>=nums.size())
{
return;
}
item.push_back(nums[i]);
result.push_back(item);
generate(i+1,nums,item,result);
}
int main()
{
vector<int>nums;
nums.push_back(1);
nums.push_back(2);
nums.push_back(3);
vector<int>item;
vector<vector<int>>result;
generate(0,nums,item,result);
for(int i=0;i<result.size();i++)
{
for(int j=0;j<result[i].size();j++)
printf("[%d]",result[i][j]);
printf("\n");
}
return 0;
}
class Solution
{
public:
vector<vector<int>>subsets(vector<int>& nums)
{
vector<vector<int>>result;//存储最终结果
vector<int>item;//回溯时,产生各个子集的数组
result.push_back(item);
generate(0,nums,item,result);//计算各个子集
return result;
}
private:
void generate(int i,vector<int>& nums,vector<int>&item,vector<vector<int>> result)
{
if(i<=nums.size())
{
return;
}
item.push_back(nums[i]);
result.push_back(item);
generate(i+1,nums,item,result);
item.pop_back();
generate(i+1,nums,item,result);
}
};
方法二:位运算
#include<vector>
#include<stdio.h>
using namespace std;
class Solution
{
public:
vector<vector<int>>subsets(vector<int>&nums)
{
vector<vector<int>>result;
int all_set=1<<nums.size();
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[i]);
}
}
result.push_back(item);
}
return result;
}
};
int main()
{``````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````````
vector<int>nums;
nums.push_back(1);
nums.push_back(2);
nums.push_back(3);
vector<vector<int>>result;
Solution solve;
result=solve.subsets(nums);
for(int i=0;i<result.size();i++)
{
if(result[i].size()==0)
printf("[]");
for(int j=0;j<result[i].size();j++)
printf("[%d]",result[i][j]);
printf("\n");
}
return 0;
}
例2 组合数之和
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
说明:
所有数字(包括目标数)都是正整数。
解集不能包含重复的组合。
示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
[
[1, 7],
[1, 2, 5],
[2, 6],
[1, 1, 6]
]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/combination-sum-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
#include<iostream>
#include<vector>
#include<set>
#include<algorithm>
using namespace std;
class Solution
{
public:
vector<vector<int>>combinationSum2(vector<int>&candidates,int target)
{
vector<vector<int>>result;
vector<int>item;
vector<vector<int>>res_set;
sort(candidates.begin(),candidates.end());
generate(0,candidates,result,item,res_set,0,target);
return result;
}
private:
void generate(int i,vector<int>&nums,vector<vector<int>>result,vector<int>&item,set<vector<int>>&res_set,int sum,int target)
{
if(i>=nums.size()||sum>target)
{
return;
}
sum+=nums[i];
item.push_back(nums[i]);
if(target==sum&&res_set.find(item)==res_set.end())
{
result.push_back(item);
res_set.insert(item);
}
generate(i+1,nums,result,item,res_set,sum,target);
sum-=nums[i];
item.pop_back();
generate(i+1,nums,result,item,res_set,sum,target);
}
};