力扣每日一题,78. 子集
我的成绩
用了将近20分钟写的,一次通过了,运气爆棚。这说明我的回溯法技能经验又+1。
不过通过后我回过头区看题目标签,
这题居然涉及位运算,我没想过哪里可以用到位运算,得去题解去看看大佬们的操作才行。
题目描述
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入: nums = [1,2,3] 输出: [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]
思路
回溯,回溯,这题和全排列一个尿性。
假如是123进行全排列,算法图解如下:
图是我用visio画的,看不清除可下载原visio文件
https://o8.cn/L12taX密码:zsnh(本地高速是下载器)
我们可以观察到这题的结果其实在全排列过程中已经出来了,如下图所示:
同时我们可以发现,存在可以进行剪枝的结点(我用蓝色框框出来的结点)它的特点是存在逆序(前面的数大于后面的数),所以在回溯过程中,可以判断当前结点是否逆序,是就直接return
if(!isBackward(path)){
res.add(new ArrayList<Integer>(path));
}else{
return;
}
private boolean isBackward(List<Integer> a) {
for (int i = 0; i < a.size()-1; i++) {
if(a.get(i)>a.get(i+1)){
return true;
}
}
return false;
}
回溯法模板如下:
回溯法模板
void backtrack(int i, int n, other parameters) {
if (i == n) {
//获取一个答案
return;
}
//一般子结点有多少个就循环多少次
for (){
backtrack(i + 1, n, other parameters);
}
}
提交代码
package 子集;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
public class Solution {
@Test
public void testBacktrace() throws Exception {
int nums[] = {1,2,3};
boolean used[] = new boolean[nums.length];
List<Integer> path = new ArrayList<Integer>();
List<List<Integer>> res = new ArrayList<List<Integer>>();
backtrace(0, nums.length, nums, used,path,res);
System.out.println(res);
}
public List<List<Integer>> subsets(int[] nums) {
boolean used[] = new boolean[nums.length];
List<Integer> path = new ArrayList<Integer>();
List<List<Integer>> res = new ArrayList<List<Integer>>();
backtrace(0, nums.length, nums, used,path,res);
return res;
}
private void backtrace(int i ,int n,int nums[],boolean used[],List<Integer> path,List<List<Integer>> res) {
if(!isBackward(path)){
res.add(new ArrayList<Integer>(path));
}else{
return;
}
//以下这个递归终止条件的判断完全可以删除,是我进行全排列观察打印结果用的。
if(i==n){
System.out.println(path);
return;
}
for (int j = 0; j < nums.length; j++) {
if(!used[j]){
used[j] = true;
path.add(nums[j]);
backtrace(i+1, n, nums, used,path,res);
path.remove(path.size()-1);
used[j] = false;
}
}
}
private boolean isBackward(List<Integer> a) {
for (int i = 0; i < a.size()-1; i++) {
if(a.get(i)>a.get(i+1)){
return true;
}
}
return false;
}
}