1.给出集合[1,2,3,4],它的大小为2(就是k)子集有[[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]。
public class Solution{
private List<Integer> temp = new ArrayList<>();
private List<List<Integer>> ens = new ArrayList<>();
public List<List<Integer>> solution(int n, int k){
//n是数组长度,k是子集的大小
dfs(1, n, k);
return ens;
}
private void dfs(int cur,int n, int k){
//剪枝操作,就是越界之后去除递归的必要性
if(temp.size() + (n - cur+1) < k){
return;
}
//达到子集大小要求后返回
if(temp.size() == k){
ens.add(new ArrayList<Integer>(temp));
return;
}
temp.add(cur);
dfs(cur+1,n,k);
temp.remove(temp.size() - 1);
//就是子集左边的数字前进一格
dfs(cur+1,n,k);
}
}
2.第一个看着限制条件比较多。那么,对于任意一个数字集合[1,3,4,7,4]要求它的所有子集,大小不作限制呢?对上面的灵活应用一下,就可以了。
class Solution {
private List<Integer> temp = new ArrayList<>();
private List<List<Integer>> ens = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
for(int i=0;i<nums.length+1;i++){
dfs(1, nums.length,i,nums);
}
return ens;
}
private void dfs(int cur, int n , int k,int[] num){
if(temp.size()+(n-cur+1) < k){
return;
}
if(temp.size() == k){
ens.add(new ArrayList<Integer>(temp));
return;
//把上面那个不规律的数组想象为一
//个与一个从0-length-1的数组的对应的数组
//例如:[1,3,4,7,4],对应[0,1,2,3,4],对第二个取子集
//再按照位置在第一个取值即可
temp.add(num[cur-1]);
dfs(cur+1, n, k, num);
temp.remove(temp.size()-1);
dfs(cur+1,n,k, num);
}
}
3.全排列[1,2],全排列[[1,2],[2,1].
class Solution{
private List<List<Integer>> ans = new ArrayList<Integer>();
private List<Integer> temp = new ArrayList<>();
public List<List<Integer>> re(int[] nums){
int n = nums.length;
for(int num:nums)
temp.add(num);
dfs(n, 0);
return ans;
}
private void dfs(int n, int cur){
if(cur == n){
ans.add(new ArrayList<Integer>(temp));
return;
}
for(int i=cur;i<n;i++){
//交换
Collections.swap(temp, i, cur);
dfs(n, cur+1);
//回溯
Collections.swap(temp, i, cur);
}
}
}