该题给咱们一个array,要求咱们找到全部不重复的子集
java
输入: nums = [1,2,3]
输出:
[
[3],
[1],
[2],
[1,2,3],
[1,3],
[2,3],
[1,2],
[]
]
复制代码
这里咱们运用backtracking算法,先sort array在此题中其实并没有意义,创建一个backtrack方法,在方法中,先创建一个新的ArrayList,而后用for loop添加新的元素,用递归向更深处搜索,搜索完后删除新添加的元素算法
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
backtrack(list, new ArrayList<>(), nums, 0);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int[] nums, int start){
list.add(new ArrayList<>(tempList));
for(int i = start; i < nums.length; i++){
tempList.add(nums[i]);
backtrack(list, tempList, nums, i+1);
tempList.remove(tempList.size()-1);
}
}
}
复制代码
该题与78几乎同样,可是涉及到了重复问题,这里咱们先将array sort,而后比较当前位与前一位,若是相同则跳过当前位。数组
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(nums);
backtrack(list, new ArrayList<>(), nums, 0);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int[] nums, int start){
list.add(new ArrayList<>(tempList));
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, i + 1);
tempList.remove(tempList.size()-1);
}
}
}
复制代码
给定两个整数 n 和 k,返回 1 ... n 中全部可能的 k 个数的组合。bash
输入: n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
复制代码
仍然采用backracking,写一个backtrack helper function,而后检测是否size是k,若是是k则把该tempList加入result listoop
class Solution {
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> list = new ArrayList<>();
if(n == 0 || k == 0) return list;
backtrack(list, new ArrayList<>(), 0, n, k);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int start, int n, int k){
if(tempList.size() == k) list.add(new ArrayList<>(tempList));
for(int i=start; i<n; i++){
tempList.add(i+1);
backtrack(list, tempList, i+1, n, k);
tempList.remove(tempList.size()-1);
}
}
}
复制代码
给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中全部可使数字和为 target 的组合。spa
candidates 中的数字能够无限制重复被选取。code
输入: candidates = [2,3,5], target = 8,
所求解集为:
[
[2,2,2,2],
[2,3,3],
[3,5]
]
复制代码
该题与以前的题目思路彻底相同,只不过断定条件为target当前与0的关系,若是等于0则直接添加,小于0则剪枝,大于0则继续向下探索,难点在于,递归时的i为0,由于每一个数字能够取无限次递归
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> list = new ArrayList<>();
backtrack(list, new ArrayList<>(), candidates, target, 0);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int[] candidates, int target, int start){
if(target < 0) return;
else if(target == 0) list.add(new ArrayList<>(tempList));
else{
for(int i=start; i<candidates.length; i++){
tempList.add(candidates[i]);
backtrack(list, tempList,candidates, target-candidates[i], i);
tempList.remove(tempList.size()-1);
}
}
}
}
复制代码
思路彻底相同,先sort而后断定当前的数字与前一个数字是否相等,若是相等则跳过rem
class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
List<List<Integer>> list = new ArrayList<>();
Arrays.sort(candidates);
backtrack(list, new ArrayList<>(), candidates, target, 0);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int[] candidates, int target, int start){
if(target < 0) return;
else if(target == 0) list.add(new ArrayList<>(tempList));
else{
for(int i=start; i<candidates.length; i++){
if(i > start && candidates[i] == candidates[i-1]) continue;
tempList.add(candidates[i]);
backtrack(list, tempList, candidates, target-candidates[i], i+1);
tempList.remove(tempList.size()-1);
}
}
}
}
复制代码
找出全部相加之和为 n 的 k 个数的组合。组合中只容许含有 1 - 9 的正整数,而且每种组合中不存在重复的数字get
77 题和 40 题的结合题,须要统计还剩余的n,并且要断定当前的tempList的size是否为k,能够直接用一个1-9的array也能够直接用进for loop
class Solution {
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> list = new ArrayList<>();
if(n == 0 || k == 0) return list;
backtrack(list, new ArrayList<>(), n, k, 0);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int n, int k, int start){
if(n == 0){
if(tempList.size() == k) list.add(new ArrayList<>(tempList));
else return;
}
else if(n < 0) return;
else{
for(int i = start; i < 9; i++){
tempList.add(i+1);
backtrack(list, tempList, n-i-1, k, i+1);
tempList.remove(tempList.size()-1);
}
}
}
}
复制代码
这道题能够用backtracking的作法,可是会超时,该用dp解法
dp[i] = 每个能到dp[i]的step的数量总和
class Solution {
public int combinationSum4(int[] nums, int target) {
int[] dp = new int[target+1];
dp[0] = 1;
for(int i = 0; i < dp.length; i++){
for(int num:nums){
dp[i] += dp[i-num];
}
}
return dp[target];
}
}
复制代码
给定一个不重复的数组,返回全部的排列组合
输入: [1,2,3]
输出:
[
[1,2,3],
[1,3,2],
[2,1,3],
[2,3,1],
[3,1,2],
[3,2,1]
]
复制代码
Main function 与以前全部题目相同,断定条件为是否长度为nums.length,为true则获取了所有元素,在for loop中要断定当前的tempList里是否已经包含了当前元素,若是包含则跳过(剪枝)
class Solution {
public List<List<Integer>> permutations(int[] nums) {
List<List<Integer>> list = new ArrayList<>();
backtrack(list, new ArrayList<>(), nums);
return list;
}
private void backtrack(List<List<Integer>> list, List<Integer> tempList, int[] nums){
if(tempList.size() == nums.length) list.add(new ArrayList<>(tempList ));
for(int i = 0; i < nums.length; i++){
if(tempList.contains(nums[i])) continue;
tempList.add(nums[i]);
backtrack(list, tempList, nums);
tempList.remove(tempList.size()-1);
}
}
}
复制代码