java回溯输出所有组合_Java中回溯问题的一般方法(子集,排列,回文分区)

Java回溯算法详解:子集、排列、回文分区
本文介绍了Java中利用回溯算法解决子集、子集带重复元素、排列、排列带重复元素、组合及回文分区问题的方法。通过示例代码详细展示了每种问题的解决方案,帮助理解回溯算法的应用。

1.求子集

给定一组不同的整数,nums,返回所有可能的子集(幂集)。

注意:解决方案集不得包含重复的子集。

例子:

Input: nums = [1,2,3]

Output:

[

[3],

[1],

[2],

[1,2,3],

[1,3],

[2,3],

[1,2],

[]

]

代码如下:

class Solution {

public List> subsets(int[] nums) {

List> list = new ArrayList();

Arrays.sort(nums);

backtrack(list,new ArrayList<>(),nums,0);

return list;

}

private void backtrack(List>list,ListtempList,int []nums,int start){

list.add(new ArrayList<>(tempList));

for(int i = start;i

tempList.add(nums[i]);

backtrack(list,tempList,nums,i+1);

tempList.remove(tempList.size()-1);

}

}

}

给定可能包含重复项,nums的整数集合,返回所有可能的子集(幂集)。

注意:解决方案集不得包含重复的子集。

例子:

Input: [1,2,2]

Output:

[

[2],

[1],

[1,2,2],

[2,2],

[1,2],

[]

]

public List> subsetsWithDup(int nums){

List> list = new ArrayList<>();

Arrays.sort(nums);

backtrack(list,new ArrayList<>(),nums,0);

return list;

}

private void backtrack(List> list,List tempList,int []nums,int start){

list.add(new ArrayList<>(new ArrayList<>(tempList));

for(int i = start;i

if(i>start && nums[i]==nums[i-1) continue;//跳过重复的数

tempList.add(nums[i]);

backtrack(list,tempList,nums,i+1);

tempList.remove(tempList.size()-1);

}

}

3.给定一组不同的整数,返回所有可能的排列。

举例:

Input: [1,2,3]

Output:

[

[1,2,3],

[1,3,2],

[2,1,3],

[2,3,1],

[3,1,2],

[3,2,1]

]

public List> permute(int [ ] nums){

List> list = new ArrayList<>();

backtrack(list,new ArrayList<>(),nums);

return list;

}

private void backtrack(List> list,List tempList,int []nums){

if(tempList.size() == nums.length){

list.add(new ArrayList<>(tempList));

}else{

for(int i = 0;i

if(tempList.contains(nums[i])) continue;

tempList.add(nums[i]);

backtrack(list,tempList,nums);

tempList.remove(tempList.size()-1);

}

}

}

4.给定可能包含重复项的数字集合,返回所有可能的唯一排列。

举例:

Input: [1,1,2]

Output:

[

[1,1,2],

[1,2,1],

[2,1,1]

]

public List> permuteUnique(int[] nums) {

List> list = new ArrayList<>();

Arrays.sort(nums);

backtrack(list, new ArrayList<>(), nums, new boolean[nums.length]);

return list;

}

private void backtrack(List> list, List tempList, int [] nums, boolean [] used){

if(tempList.size() == nums.length){

list.add(new ArrayList<>(tempList));

} else{

for(int i = 0; i < nums.length; i++){

if(used[i] || i > 0 && nums[i] == nums[i-1] && !used[i - 1]) continue;

used[i] = true;

tempList.add(nums[i]);

backtrack(list, tempList, nums, used);

used[i] = false;

tempList.remove(tempList.size() - 1);

}

}

}

给定一组候选数字(候选者)(没有重复)和目标数量(目标),找到候选人数总和目标的候选人中的所有独特组合。

可以从候选者无限次数中选择相同的重复数字。

注意:

所有数字(包括目标)都是正整数。

解决方案集不得包含重复的组合。

举例:Input: candidates = [2,3,6,7], target = 7,

A solution set is:

[

[7],

[2,2,3]

]

Input: candidates = [2,3,5], target = 8,

A solution set is:

[

[2,2,2,2],

[2,3,3],

[3,5]

]

public List> combinationSum(int[] nums, int target) {

List> list = new ArrayList<>();

Arrays.sort(nums);

backtrack(list, new ArrayList<>(), nums, target, 0);

return list;

}

private void backtrack(List> list, List tempList, int [] nums, int remain, int start){

if(remain < 0) return;

else if(remain == 0) list.add(new ArrayList<>(tempList));

else{

for(int i = start; i < nums.length; i++){

tempList.add(nums[i]);

backtrack(list, tempList, nums, remain - nums[i], i); // 不是i+1,因为我们可以

//接受重复的数

tempList.remove(tempList.size() - 1);

}

}

}

给定候选数字(候选者)和目标数量(目标)的集合,找到候选人数量总和为目标的候选人中的所有独特组合。

候选人中的每个号码只能在组合中使用一次。

注意:

所有数字(包括目标)都是正整数。

解决方案集不得包含重复的组合。

举例:

Input: candidates = [10,1,2,7,6,1,5], target = 8,

A solution set is:

[

[1, 7],

[1, 2, 5],

[2, 6],

[1, 1, 6]

]

Input: candidates = [2,5,2,1,2], target = 5,

A solution set is:

[

[1,2,2],

[5]

]

public List> combinationSum2(int[] nums, int target) {

List> list = new ArrayList<>();

Arrays.sort(nums);

backtrack(list, new ArrayList<>(), nums, target, 0);

return list;

}

private void backtrack(List> list, List tempList, int [] nums, int remain, int start){

if(remain < 0) return;

else if(remain == 0) list.add(new ArrayList<>(tempList));

else{

for(int i = start; i < nums.length; i++){

if(i > start && nums[i] == nums[i-1]) continue; // 跳过重复的数

tempList.add(nums[i]);

backtrack(list, tempList, nums, remain - nums[i], i + 1);

tempList.remove(tempList.size() - 1);

}

}

}

给定字符串s,分区s使得分区的每个子字符串都是回文。

返回s的所有可能的回文分区。

举例:

Input: “aab”

Output:

[

[“aa”,“b”],

[“a”,“a”,“b”]

]

public List> partition(String s) {

List> list = new ArrayList<>();

backtrack(list, new ArrayList<>(), s, 0);

return list;

}

public void backtrack(List> list, List tempList, String s, int start){

if(start == s.length())

list.add(new ArrayList<>(tempList));

else{

for(int i = start; i < s.length(); i++){

if(isPalindrome(s, start, i)){

tempList.add(s.substring(start, i + 1));

backtrack(list, tempList, s, i + 1);

tempList.remove(tempList.size() - 1);

}

}

}

}

public boolean isPalindrome(String s, int low, int high){

while(low < high)

if(s.charAt(low++) != s.charAt(high--)) return false;

return true;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值