给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以无限制重复被选取。
class Solution {
public List<List<Integer>> combinationSum(int[] candidates, int target) {
List<List<Integer>> listAll = new ArrayList<>();
List<Integer> list = new ArrayList<>();
Arrays.sort(candidates);
find(listAll, list, candidates, target, 0);
return listAll;
}
public void find(List<List<Integer>> listAll, List<Integer> temp, int[] candidates, int target, int index) {
if(target == 0) {
listAll.add(temp);
return;
}
if(target < candidates[0]) return;
for(int i = index; i < candidates.length && candidates[i] <= target; i++) {
List<Integer> list = new ArrayList<>(temp);
list.add(candidates[i]);
find(listAll, list, candidates, target-candidates[i], i);
}
}
}
给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次。
class Solution {
public List<List<Integer>> combinationSum2(int[] candidates, int target) {
Arrays.sort(candidates);
List<List<Integer>> res = new ArrayList<>();
find(res, 0, 0, new ArrayList<Integer>(), candidates, target);
return res;
}
public void find(List<List<Integer>> res, int index, int sum, List<Integer> tmp_list, int[] candidates, int target) {
if(sum == target) {
res.add(new ArrayList<>(tmp_list));
return;
}
for(int i = index; i < candidates.length; i++) {
if (sum + candidates[i] > target) break;
if (i > index && candidates[i] == candidates[i - 1]) continue; //去重
tmp_list.add(candidates[i]);
find(res, i+1, sum + candidates[i], tmp_list, candidates, target);
tmp_list.remove(tmp_list.size()-1); //去重,防止一个组合里面有相同的数,上面是防止有两个相同的数组
}
}
}
找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
class Solution {
public List<List<Integer>> combinationSum3(int k, int n) {
int[] nums = new int[]{1,2,3,4,5,6,7,8,9};
List<List<Integer>> ans = new ArrayList<List<Integer>>();
dfs(nums,0,n,k,new ArrayList<Integer>(),ans);
return ans;
}
private void dfs(int[] nums,int i,int left,int k,ArrayList<Integer> cur,List<List<Integer>> ans) {
if (left < 0) return ;
if (k == 0) {
if (left == 0) {
ans.add(new ArrayList<Integer>(cur));
return ;
} else return ;
}
for (int j = i;j < nums.length;j++) {
if (nums[j] > left) break;
cur.add(nums[j]);
dfs(nums,j+1,left - nums[j],k-1,cur,ans);
cur.remove(cur.size()-1);
}
}
}
给定一个没有重复数字的序列,返回其所有可能的全排列。
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
List<Integer> t = new ArrayList<>();
for(int i = 0; i < nums.length; i++) {
t.add(nums[i]);
find(res, t, nums);
t.remove(0);
}
return res;
}
private void find(List<List<Integer>> res, List<Integer> tmp, int[] nums) {
if(tmp.size() == nums.length) {
res.add(new ArrayList<>(tmp));
return;
}
for(int i = 0; i < nums.length; i++) {
if(!tmp.contains(nums[i])) {
tmp.add(nums[i]);
find(res, tmp, nums);
tmp.remove(tmp.size()-1);
}
}
}
}
/* 方法二:不对数组进行加减操作,而是交换,这种方法更快 ----------------------------------*/
class Solution {
public List<List<Integer>> permute(int[] nums) {
//思路:运用递归的方法,
int len=nums.length;//记录数组的长度
int first=0;//
List<List<Integer>> output=new LinkedList<List<Integer>>();//建立一个输出的数组
//将数组转换成链表的形式,是因为定义的输出数组中的元素要求List类型的。
ArrayList<Integer> nums_li=new ArrayList<Integer>();
for(int num:nums){
nums_li.add(num);
}
digui(len,output,nums_li,first);//调用递归函数
return output;
}
//递归函数
public static void helper(int len,List<List<Integer>> output
,ArrayList<Integer>nums_li,int first){
//结束条件:当到数组中的最后一个元素时,即已经排列组合完毕,则输出
if(first==len){
output.add(new ArrayList<Integer>(nums_li));
}
int i;
for(i=first;i<len;i++){
Collections.swap(nums_li,first,i);
helper(len,output,nums_li,first+1);
Collections.swap(nums_li,first,i);
}
}
}
/* 方法三: 三个for循环,其实和for循环很像 -------------------------------------*/
class Solution {
public List<List<Integer>> permute(int[] nums) {
List<List<Integer>> result = new ArrayList<List<Integer>>();
List<Integer> l1 = new ArrayList<Integer>();
l1.add(nums[0]);
result.add(l1);
for(int i = 1;i<nums.length;i++){
List<List<Integer>> resultx = new ArrayList<List<Integer>>();
for(List<Integer> list:result){
// System.out.println(list);
for(int j =0;j<=list.size();j++ ){
List<Integer> list2 = new ArrayList<Integer>();
list2.addAll(list);
list2.add(j,nums[i]);
resultx.add(list2);
}
}
result = resultx;
}
return result;
}
}
给定一个可包含重复数字的序列,返回所有不重复的全排列。
class Solution {
public List<List<Integer>> permuteUnique(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
// 添加visited数组,区分相等数字,以及同一排列里面相等但不相同的数字
int[] visited = new int[nums.length];
backtrack(res, nums, visited, new ArrayList<Integer>());
return res;
}
private void backtrack(List<List<Integer>> res, int[] nums, int[] visited, ArrayList<Integer> tmp) {
if (tmp.size() == nums.length) {
res.add(new ArrayList<>(tmp));
return;
}
for (int i = 0; i < nums.length; i++) {
if (visited[i] == 1 || (i > 0 && visited[i - 1] == 0 && nums[i - 1] == nums[i])) continue;
visited[i] = 1;
tmp.add(nums[i]);
backtrack(res, nums, visited, tmp);
tmp.remove(tmp.size() - 1);
visited[i] = 0;
}
}
}
给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
class Solution {
public List<List<Integer>> subsets(int[] nums) {
ArrayList<List<Integer>> res = new ArrayList<>();
subsetsCore(res, new ArrayList<Integer>(), nums, 0);
return res;
}
private void subsetsCore(ArrayList<List<Integer>> res, ArrayList<Integer> list, int[] nums, int index) {
res.add(new ArrayList<>(list));
for (int i = index; i < nums.length; i++) {
list.add(nums[i]);
subsetsCore(res, list, nums, i + 1);
list.remove(list.size() - 1);
}
}
}
/* 方法二: 两个for循环完成 -------------------------------------*/
class Solution {
public List<List<Integer>> subsets(int[] nums) {
List<List<Integer>> result = new ArrayList<>();
result.add(new ArrayList<>());
for(int n : nums){
int size = result.size();
for(int i=0; i<size; i++){
List<Integer> subset = new ArrayList<>(result.get(i));
subset.add(n);
result.add(subset);
}
}
return result;
}
}
给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
class Solution {
public List<List<Integer>> subsetsWithDup(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
backTrack(res,nums,new ArrayList<Integer>(),0);
return res;
}
public void backTrack(List<List<Integer>> res,int []nums,List<Integer>tmp,int start){
res.add(new ArrayList<>(tmp));
for(int i=start;i<nums.length;i++){
if(i > start && nums[i] == nums[i-1]) continue;
tmp.add(nums[i]);
backTrack(res,nums,tmp,i+1);
tmp.remove(tmp.size()-1);
}
}
}
给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
class Solution {
public List<List<Integer>> combine(int n, int k) {
List<List<Integer>> res = new ArrayList<>();
helper(n, k, 1, res, new ArrayList<Integer>());
return res;
}
private void helper(int n, int k, int start, List<List<Integer>> res, List<Integer> temp) {
if(temp.size() == k) {
res.add(new ArrayList<>(temp));
return;
}
for(int j = start; j <= n - (k - temp.size()) + 1; j++) {
temp.add(j);
helper(n, k, j+1, res, temp);
temp.remove(temp.size()-1);
}
}
}
给定一个只包含数字的字符串,复原它并返回所有可能的 IP 地址格式。
class Solution {
public List<String> restoreIpAddresses(String s) {
List<String> res = new ArrayList<>();
helper(0, "", 4, s, res, s.length());
return res;
}
private void helper(int start, String temp, int flag, String s, List<String> list, int len) {
if(start==len && flag==0) {
list.add(temp.substring(0, temp.length()-1)); //-1是为了把最后的"."去掉
return;
}
if(flag < 0) return;
for(int i = start; i < start+3; i++) {
if(i < len) {
if(start==i && s.charAt(i)=='0') { //如果是子字符串的首位且为0
helper(i+1, temp+s.charAt(i)+".", flag-1, s, list, len);
break;
}
if(Integer.parseInt(s.substring(start, i+1)) <= 255)
helper(i+1, temp+s.substring(start, i+1)+".", flag-1,
s, list, len);
}
}
}
}
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/permutation-sequence