回溯问题学习总结
无重复元素不可复选
//子集问题
static List<List<Integer>> res=new LinkedList<>();
static LinkedList<Integer> track=new LinkedList<>();
//无重复元素
public static List<List<Integer>> subsets(int[] nums) {
back(nums,0);
return res;
}
static void back(int[] nums,int start){
res.add(new LinkedList<>(track));
for (int i=start;i<nums.length;i++){
track.add(nums[i]);
back(nums,i+1);
track.removeLast();
}
}
//组合问题
static List<List<Integer>> res=new LinkedList<>();
static LinkedList<Integer> track=new LinkedList<>();
public static List<List<Integer>> combine(int n, int k) {
backtrack(n,1,k);
return res;
}
static void backtrack(int n,int start,int k){
if(track.size()==k){
res.add(new LinkedList<>(track));
}
for (int i=start;i<=n;i++){
track.add(i);
backtrack(n,i+1,k);
track.removeLast();
}
}
//排列问题
static List<List<Integer>> res=new LinkedList<>();
static LinkedList<Integer> track=new LinkedList<>();
public static List<List<Integer>> permute(int[] nums) {
back(nums,track);
return res;
}
static void back(int[] nums,LinkedList<Integer> track){
if(track.size()== nums.length){
res.add(new LinkedList<>(track));
return;
}
for (int i=0;i<nums.length;i++){
if(track.contains(nums[i])) continue;
track.add(nums[i]);
back(nums,track);
track.removeLast();
}
}
有重复元素不可复选
//子集问题
List<List<Integer>> res = new LinkedList<>();
LinkedList<Integer> track = new LinkedList<>();
public List<List<Integer>> subsetsWithDup(int[] nums) {
// 先排序,让相同的元素靠在一起
Arrays.sort(nums);
backtrack(nums, 0);
return res;
}
void backtrack(int[] nums, int start) {
// 前序位置,每个节点的值都是一个子集
res.add(new LinkedList<>(track));
for (int i = start; i < nums.length; i++) {
// 剪枝逻辑,值相同的相邻树枝,只遍历第一条
if (i > start && nums[i] == nums[i - 1]) {
continue;
}
track.addLast(nums[i]);
backtrack(nums, i + 1);
track.removeLast();
}
}
//组合问题
List<List<Integer>> res = new LinkedList<>();
LinkedList<Integer> track = new LinkedList<>();
int trackSum = 0;
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
if (candidates.length == 0) {
return res;
}
// 先排序,让相同的元素靠在一起
Arrays.sort(candidates);
backtrack(candidates, 0, target);
return res;
}
void backtrack(int[] nums, int start, int target) {
if (trackSum == target) {
res.add(new LinkedList<>(track));
return;
}
if (trackSum > target) {
return;
}
for (int i = start; i < nums.length; i++) {
// 剪枝逻辑,值相同的树枝,只遍历第一条
if (i > start && nums[i] == nums[i - 1]) {
continue;
}
track.add(nums[i]);
trackSum += nums[i];
backtrack(nums, i + 1, target);
track.removeLast();
trackSum -= nums[i];
}
}
//排列问题
List<List<Integer>> res = new LinkedList<>();LinkedList<Integer> track = new LinkedList<>();
boolean[] used;
public List<List<Integer>> permuteUnique(int[] nums) {
// 先排序,让相同的元素靠在一起
Arrays.sort(nums);
used = new boolean[nums.length];
backtrack(nums);
return res;
}
void backtrack(int[] nums) {
if (track.size() == nums.length) {
res.add(new LinkedList(track));
return;
}
for (int i = 0; i < nums.length; i++) {
if (used[i]) {
continue;
}
// 新添加的剪枝逻辑,固定相同的元素在排列中的相对位置
if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) {
continue;
}
track.add(nums[i]);
used[i] = true;
backtrack(nums);
track.removeLast();
used[i] = false;
}
}
无重复元素可复选
//子集问题
List<List<Integer>> res = new LinkedList<>();
LinkedList<Integer> track = new LinkedList<>();
int trackSum = 0;
public List<List<Integer>> combinationSum(int[] candidates, int target) {
if (candidates.length == 0) {
return res;
}
backtrack(candidates, 0, target);
return res;
}
void backtrack(int[] nums, int start, int target) {
if (trackSum == target) {
res.add(new LinkedList<>(track));
return;
}
if (trackSum > target) {
return;
}
for (int i = start; i < nums.length; i++) {
trackSum += nums[i];
track.add(nums[i]);
backtrack(nums, i, target);
trackSum -= nums[i];
track.removeLast();
}
}
//排列问题
List<List<Integer>> res = new LinkedList<>();
LinkedList<Integer> track = new LinkedList<>();
public List<List<Integer>> permuteRepeat(int[] nums) {
backtrack(nums);
return res;
}
void backtrack(int[] nums) {
if (track.size() == nums.length) {
res.add(new LinkedList(track));
return;
}
for (int i = 0; i < nums.length; i++) {
track.add(nums[i]);
backtrack(nums);
track.removeLast();
}