回溯算法-【全排列】【组合总和】【n皇后】【子集】

回溯算法

 回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就“回溯”返回,尝试别的路径。即从一条路往前走,能进则进,不能进则退回来,换一条路再试。

如何使用回溯算法

 回溯我认为也就是一种递归,有以下四个参数,当然不一定是我所举例的类型,要看题目而定
  (1)一个全局变量集合保存所有满足条件的答案,举例:List<List> res
  (2)一个集合保存一个满足条件的答案,举例:List tmpList
核心:根据各个题情况变换

  for (int i = start; i <= n; i++) {
  		//add进去的值根据题意变换
                tmplist.add(i);
                //递归,这里根据题意变换回溯,这仅仅是个例子
                backtrack( k - 1, n, i+1,tmplist, result);
                //将这个集合清空,方便下一个满足条件的答案
                tmplist.remove(tmplist.size()-1);
            }
    

leetcode_【46】全排列 I

https://leetcode-cn.com/problems/permutations/

题目描述:
 给定一个没有重复数字的序列,返回其所有可能的全排列。
输入:
  [1,2,3]
输出:
  [
   [1,2,3],
   [1,3,2],
   [2,1,3],
   [2,3,1],
   [3,1,2],
   [3,2,1]
   ]

解题思路:

  回溯算法:

  • 将第j个数字与第 j , j +1 , j + 2 ,…, len(nums) - 1个数字分别交换,得到 len(nums) - j 种情况;
  • 在每种情况下递归,将第j+1处数字与第j+1,j+2,…,len(nums) - 1处数字分别交换;
    • 每个递归跳出后,要将交换过的元素还原,这样才能实现第一条所说的内容。
    • 直到j == len(nums) - 1,代表此种交换组合下已经交换完毕,记录答案。

代码

第一版:

import java.util.ArrayList;
import java.util.List;
//执行用时 :41 ms, 在所有 Java 提交中击败了5.01%的用户
//内存消耗 :44.4 MB, 在所有 Java 提交中击败了5.03%的用户
public class Solution {
   public static void main(String[] args) {
       int [] arr = {1,2,1};
       permute(arr);
   }
   public static List<List<Integer>> permute(int[] nums) {
       List<List<Integer>> res = new ArrayList<>();
       backTrace(nums,0,new ArrayList<>(),res);
       return res;
   }

   private static void backTrace(int[] nums, int start,ArrayList<Integer> tempList, List<List<Integer>> res) {
       //start为左边界值,要跟右边界的数进行交换
       if(start == nums.length){
           if(!res.contains(tempList)){
               res.add(new ArrayList<>(tempList));
           }
       }
       for(int i = start;i<nums.length;i++){
           //将第j个数字与第 j , j +1 , j + 2 ,..., len(nums) - 1个数字分别交换
           swap(nums,start,i);
           tempList.add(nums[start]);
           backTrace(nums,start+1,tempList,res);
           tempList.remove(tempList.size()-1);
           // 每个递归跳出后,要将交换过的元素还原
           swap(nums,start,i);
       }
   }
   //交换
   private static void swap(int[] nums, int start, int i) {
       int temp = nums[start];
       nums[start] = nums[i];
       nums[i] = temp;
   }
}

第二版:leetcode官网解答

这里有一个回溯函数,使用第一个整数的索引作为参数 backtrack(first)。

  • 如果第一个整数有索引 n,意味着当前排列已完成。
  • 遍历索引 first 到索引 n - 1 的所有整数。
    • 在排列中放置第 i 个整数, 即 swap(nums[first], nums[i]).
    • 继续生成从第 i 个整数开始的所有排列: backtrack(first + 1).
    • 现在回溯,即通过 swap(nums[first], nums[i]) 还原.
//执行用时 :3 ms, 在所有 Java 提交中击败了87.64%的用户
//内存消耗 :38.5 MB, 在所有 Java 提交中击败了67.89%的用户
class Solution {
   public void backtrack(int n,ArrayList<Integer> nums, List<List<Integer>> output, int first) {
       //如果第一个整数有索引 n,意味着当前排列已完成。
       if (first == n)
           output.add(new ArrayList<Integer>(nums));
       // 遍历索引 first 到索引 n - 1 的所有整数。
       for (int i = first; i < n; i++) {
           //在排列中放置第 i 个整数
           Collections.swap(nums, first, i);
           //  继续生成从第 i 个整数开始的所有排列
            backtrack(n, nums, output, first + 1);
           //回溯
           Collections.swap(nums, first, i);
       }
   }

   public List<List<Integer>> permute(int[] nums) {
       List<List<Integer>> output = new LinkedList();

       // convert nums into list since the output is a list of lists
       ArrayList<Integer> nums_lst = new ArrayList<Integer>();
       for (int num : nums)
           nums_lst.add(num);

       int n = nums.length;
       backtrack(n, nums_lst, output, 0);
       return output;
   }
}

leetcode_【47】全排列 II

https://leetcode-cn.com/problems/permutations-ii/

题目描述:
 给定一个可能包含重复数字的序列,返回其所有可能的不重复全排列。
输入:
  [1,1,2]
输出:
  [
   [1,1,2],
   [1,2,1],
   [2,1,1],
   ]

代码

第一版:

import java.util.ArrayList;
import java.util.List;
//执行用时 :742 ms, 在所有 Java 提交中击败了8.80%的用户
//内存消耗 :45.7 MB, 在所有 Java 提交中击败了44.99%的用户
public class Solution{
        public static  List<List<Integer>> permuteUnique(int[] nums) {
            List<List<Integer>> res = new ArrayList<>();
            backTrace(nums,0,new ArrayList<>(),res);
            return res;
        }

        private static void backTrace(int[] nums, int start,ArrayList<Integer> tempList, List<List<Integer>> res) {
            //start为边界值
            if(start == nums.length){
                //加了这一句
                if(!res.contains(tempList)){
                    res.add(new ArrayList<>(tempList));
                }
            }
            for(int i = start;i<nums.length;i++){
                swap(nums,start,i);
                tempList.add(nums[start]);
                backTrace(nums,start+1,tempList,res);
                tempList.remove(tempList.size()-1);
                swap(nums,start,i);
            }
        }
        
        private static void swap(int[] nums, int start, int i) {
            int temp = nums[start];
            nums[start] = nums[i];
            nums[i] = temp;
        }
    }


优化的第二版:leetcode官网解答
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

//执行用时 :6 ms, 在所有 Java 提交中击败了63.63%的用户
//内存消耗 :42.8 MB, 在所有 Java 提交中击败了76.28%的用户
public class Solution {

    private List<List<Integer>> res = new ArrayList<>();
    private boolean[] used;

    private void findPermuteUnique(int[] nums, int depth, Stack<Integer> stack) {
        if (depth == nums.length) {
            res.add(new ArrayList<>(stack));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (!used[i]) {
                // 修改 2:因为排序以后重复的数一定不会出现在开始,故 i > 0
                // 和之前的数相等,并且之前的数还未使用过,只有出现这种情况,才会出现相同分支
                // 这种情况跳过即可
                if (i > 0 && nums[i] == nums[i - 1] && !used[i - 1]) {
                    continue;
                }
                used[i] = true;
                stack.add(nums[i]);
                findPermuteUnique(nums, depth + 1, stack);
                stack.pop();
                used[i] = false;
            }
        }
    }

    public List<List<Integer>> permuteUnique(int[] nums) {
        int len = nums.length;
        if (len == 0) {
            return res;
        }
        // 修改 1:首先排序,之后才有可能发现重复分支
        Arrays.sort(nums);
        used = new boolean[len];
        findPermuteUnique(nums, 0, new Stack<>());
        return res;
    }

    public static void main(String[] args) {
        int[] nums = {1, 1, 2};
        Solution solution = new Solution();
        List<List<Integer>> permuteUnique = solution.permuteUnique(nums);
        System.out.println(permuteUnique);
    }
}

leetcode_【77】组合

https://leetcode-cn.com/problems/combinations/

 给定两个整数 n 和 k,返回 1 … n 中所有可能的 k 个数的组合。
示例:
输入:
  n = 4, k = 2
输出:
   [
   [2,4],
   [3,4],
   [2,3],
   [1,2],
   [1,3],
   [1,4],
   ]

//执行用时 :40 ms, 在所有 Java 提交中击败了52.77%的用户
//内存消耗 :52.5 MB, 在所有 Java 提交中击败了26.41%的用户
public class Solution {
   public static List<List<Integer>> combine(int n, int k) {
       List<List<Integer>> res = new ArrayList<>();
       backtrack(k,n,1,new ArrayList(),res);
       return res;
   }
   public static void backtrack(int k,int n,int start,List<Integer> tmplist,List<List<Integer>> result){
       if(k == 0){
           result.add(new ArrayList<>(tmplist));
       }else {
           for (int i = start; i <= n; i++) {
               tmplist.add(i);
               //递归,这里回溯 从 i+1  ~ n 中 k-1 个数的组合,直到k == 0就可将这次结果存到res里面
               backtrack( k - 1, n, i+1,tmplist, result);
               tmplist.remove(tmplist.size()-1);
           }
       }
   }
}

leetcode_【39】组合总和 I

   https://leetcode-cn.com/problems/combination-sum/

 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以>使数字和为 target 的组合。
 candidates 中的数字可以无限制重复被选取。
说明:
  (1)所有数字(包括 target)都是正整数。
 (2)解集不能包含重复的组合。
示例 1:
输入:

   candidates = [2,3,6,7], target = 7,
所求解集为:
   [
   [7],
   [2,2,3]
   ]
示例 2:
输入:

  candidates = [2,3,5], target = 8,
所求解集为:
  [
  [2,2,2,2],
   [2,3,3],
   [3,5]
  ]

代码

//执行用时 :7 ms, 在所有 Java 提交中击败了81.11%的用户
//内存消耗 :39.1 MB, 在所有 Java 提交中击败了87.66%的用户
class Solution {
    public static List<List<Integer>> combinationSum(int[] candidates, int target) {
          //存放结果
          List<List<Integer>> res = new ArrayList<>();
          //排序
          Arrays.sort(candidates);
          //从第一个数开始递归
          calculate(candidates,target,0,new ArrayList<>(),res);

          return res;
      }
     public static void calculate(int[] candidates,int target,int start,ArrayList<Integer> tmpList,List<List<Integer>> result) {
        //回溯
        if (target < 0) {
            return;
        }
        //存入结果集
        else if (target == 0) {
            result.add(new ArrayList<>(tmpList));
            return;
        } else {
            for (int i = start; i < candidates.length && target >= candidates[i]; i++) {
                //加入
                tmpList.add(candidates[i]);
                //递归,candidates 中的数字可以使用无数次,故start还是从 i 开始
                calculate( candidates, target - candidates[i], i, tmpList,result);
                //清空所得到的一次结果的list
                tmpList.remove(tmpList.size() - 1);
            }
        }
    }

leetcode_【40】组合总和 II

   https://leetcode-cn.com/problems/combination-sum-ii/

  给定一个数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的数字可以只能使用一次。
说明:
  (1)所有数字(包括 target)都是正整数。
 (2)解集不能包含重复的组合。
输入:
  candidates = [10,1,2,7,6,1,5], target = 8,
所求解集为:
   [
   [1, 7],
   [1, 2, 5],
   [2, 6],
   [1, 1, 6]
   ]
示例 2:
输入:

   candidates = [2,5,2,1,2], target = 5,
所求解集为:
   [
  [1,2,2],
   [5]
   ]

代码

//执行用时 :30 ms, 在所有 Java 提交中击败了22.59%的用户
//内存消耗 :45 MB, 在所有 Java 提交中击败了27.34%的用户
public class Solution {
  public static List<List<Integer>> combinationSum2(int[] candidates, int target) {
      List<List<Integer>> res = new ArrayList<>();
      //排序
      Arrays.sort(candidates);
      //从下标为0,目标为target的开始回溯
      backTrace(candidates,target,0,new ArrayList<>(),res);
      return res;
  }

  private static void backTrace(int[] candidates, int target,int start, ArrayList<Integer> tmpList, List<List<Integer>> res) {
      if(target<0)
          return;
       //
      else if(target == 0){
         //解集不能包含重复的组合。 
          Collections.sort(tmpList);
          if(!res.contains(tmpList)){
              res.add(new ArrayList<>(tmpList));
          }
      }else {
          for (int i = start; i < candidates.length && target >= candidates[i]; i++) {
              tmpList.add(candidates[i]);
              //回溯,因为candidates 中的数字可以只能使用一次,所以这里start变成了i+1
              backTrace(candidates, target - candidates[i], i + 1, tmpList, res);
              tmpList.remove(tmpList.size() - 1);
          }
      }
  }

leetcode_【216】组合总和III

https://leetcode-cn.com/problems/combination-sum-iii/submissions/

  找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。
说明:
 所有数字都是正整数。
  解集不能包含重复的组合。
示例 1:
输入:

   k = 3, n = 7
输出:
   [[1,2,4]]
示例 2:
输入:

  k = 3, n = 9
输出:
   [[1,2,6], [1,3,5], [2,3,4]]

代码

//执行用时 :5 ms, 在所有 Java 提交中击败了8.96%的用户
//内存消耗 :34.1 MB, 在所有 Java 提交中击败了28.88%的用户
class Solution {
   public static List<List<Integer>> combinationSum3(int k, int n) {
       List<List<Integer>> res = new ArrayList<>();
       backTrace(k,n,1,new ArrayList<>(),res);
       return res;
   }

   private static void backTrace(int k, int target,int start, ArrayList<Integer> tmpList, List<List<Integer>> res) {
       if(0 == k && target == 0){
           Collections.sort(tmpList);
           if(!res.contains(tmpList))
               res.add(new ArrayList<>(tmpList));
       }else{
        // 组合数中只包含1-9的数,故i<=9
           for(int i = start;i <= 9 ;i++){
               tmpList.add(i);
               backTrace(k-1,target - i,i+1,tmpList,res);
               tmpList.remove(tmpList.size()-1);
           }
       }
   }
}

leetcode_【377】组合总和 IV

 给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数。
示例:
   nums = [1, 2, 3]
  target = 4
所有可能的组合为:
   (1, 1, 1, 1)
   (1, 1, 2)
   (1, 2, 1)
   (1, 3)
   (2, 1, 1)
   (2, 2)
   (3, 1)
请注意,顺序不同的序列被视作不同的组合。
因此输出为 7。

代码

回溯超出内存限制

public static int combinationSum4(int[] nums, int target) {
     List<List<Integer>> res = new ArrayList<>();
     Arrays.sort(nums);
     backTrace(nums,target,0,new ArrayList<>(),res);
     return res.size();
 }

private static void backTrace(int[] nums, int target, int start, ArrayList<Integer> tmpList, List<List<Integer>> res) {
     if(target < 0){
         return;
     }else if(target == 0){
         res.add(new ArrayList<>(tmpList));
     }else{
         for(int i = 0;i<nums.length && target >= nums[i];i++){
             tmpList.add(nums[i]);
             backTrace(nums,target - nums[i],i,tmpList,res);
             tmpList.remove(tmpList.size()-1);
         }
     }
}

动态规划:dp[i] 代表组成i 能有多少种组合数,即dp[1] = 2代表 和为1的组合个数为2

  • 初始化
    • dp[0] = 1;即组成和为0的组合数为1,即都nums里面的数都不取
  • 状态转移方程:
    • dp[i]=dp[ i - nums[0] ]+dp[ i - nums[1] ]+dp[ i - nums[2] ] + ...
      举个例子 : 比如nums=[1,3,4],target=7;dp[7]=dp[6]+dp[4]+dp[3]
//执行用时 :5 ms, 在所有 Java 提交中击败了68.54%的用户
//内存消耗 :34.3 MB, 在所有 Java 提交中击败了39.00%的用户
public static int combinationSum6(int[] nums, int target) {
    int dp[] = new int[target + 1];
    //初始化
    dp[0] = 1;
    for(int i = 1;i<=target;i++){
        for(int j = 0;j<nums.length;j++){
            if(i - nums[j] >= 0 ){
                dp[i] += dp[i-nums[j]];
            }
        }
    }
    return dp[target];
}

leetcode_【51】N皇后 I

https://leetcode-cn.com/problems/n-queens/

  n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
  给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
  每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
示例:
输入:

  4
输出:
    [
    [".Q…", // 解法 1
    “…Q”,
    “Q…”,
    “…Q.” ],
    [ “…Q.”, // 解法 2
    “Q…”,
    “…Q”,
    “.Q…”]
    ]
解释: 4 皇后问题存在两个不同的解法。

代码

  • 回溯函数 backtrack(row = 0).
    • 从第一个 row = 0 开始.
    • 循环列并且试图在每个 column 中放置皇后.
      • 如果方格 (row, column) 不在攻击范围内
        • (row, column) 方格上放置皇后
        • 排除对应行,列和两个对角线的位置。
        • If 所有的行被考虑过,row == NunOfQueen
          • 意味着我们找到了一个解
        • else
          • 继续考虑接下来的皇后放置 backtrack(row + 1).
        • 回溯:将在 (row, column) 方格的皇后移除.
package leetcode.Arrays.回溯;

import java.lang.reflect.Array;
import java.util.*;
//执行用时 :9 ms, 在所有 Java 提交中击败了53.89%的用户
//内存消耗 :39.3 MB, 在所有 Java 提交中击败了84.75%的用户
public class Main_51 {
    public static List<List<String>> solveNQueens(int n) {
        //用于存储行
        List<Integer> col = new ArrayList<>();
        //用于存储正对角线
        List<Integer> z_diagonal = new ArrayList<>();
        //用于存储负对角线
        List<Integer> f_diagonal = new ArrayList<>();
        //存储结果
        List<List<String>> res = new ArrayList<>();
        //从第一个row = 0开始
        backtrack(0, n, res, new ArrayList<String>(), col, z_diagonal, f_diagonal);
        return res;
    }
    public static void backtrack(int row, int NumOfQueen, List<List<String>> res, ArrayList<String> tmplist, List<Integer> col, List<Integer> z_diagonal, List<Integer> f_diagonal) {
        //到达了最后一行
        if (row == NumOfQueen) {
            res.add(new ArrayList<>(tmplist));
            return;
        }
        //从第0列开始遍历
        for (int column = 0; column < NumOfQueen; column++) {
            //如果不在攻击范围内(不在同一行或者同一列 && 负对角线和相等 &&  正对角线差相等)
            if (!col.contains(column) && !f_diagonal.contains(row + column) && !z_diagonal.contains(row - column)) {
                col.add(column);
                f_diagonal.add(row + column);
                z_diagonal.add(row - column);
                char[] s = new char[NumOfQueen];
                Arrays.fill(s, '.');
                //这一行的j位置放皇后
                s[column] = 'Q';
                tmplist.add(new String(s));
                //回溯算法
                backtrack(row+1,NumOfQueen,res,tmplist,col,z_diagonal,f_diagonal);
                tmplist.remove(tmplist.size() - 1);
                col.remove(Integer.valueOf(column));
                f_diagonal.remove(Integer.valueOf(row + column));
                z_diagonal.remove(Integer.valueOf(row - column));
            }
        }
    }
   
}

leetcode_【52】N皇后 II

https://leetcode-cn.com/problems/n-queens-ii/

  n 皇后问题研究的是如何将 n 个皇后放置在 n×n 的棋盘上,并且使皇后彼此之间不能相互攻击。
  给定一个整数 n,返回所有不同的 n 皇后问题的解决方案。
  每一种解法包含一个明确的 n 皇后问题的棋子放置方案,该方案中 ‘Q’ 和 ‘.’ 分别代表了皇后和空位。
示例:
输入:

  4
输出:
  2
解释:4皇后存在两种不同的解法
    [
    [".Q…", // 解法 1
    “…Q”,
    “Q…”,
    “…Q.” ],
    [ “…Q.”, // 解法 2
    “Q…”,
    “…Q”,
    “.Q…”]
    ]

如leetcode_【51】代码返回res.size();

代码

//执行用时 :29 ms, 在所有 Java 提交中击败了5.45%的用户
//内存消耗 :34.8 MB, 在所有 Java 提交中击败了41.25%的用户
public class Solution {
 public static int totalNQueens(int n) {
     //用于存储行
     List<Integer> col = new ArrayList<>();
     //用于存储正对角线
     List<Integer> z_diagonal = new ArrayList<>();
     //用于存储负对角线
     List<Integer> f_diagonal = new ArrayList<>();
     //存储结果
     List<List<String>> res = new ArrayList<>();
     //从第一个row = 0开始
     backtrack(0, n, res, new ArrayList<String>(), col, z_diagonal, f_diagonal);
     return res.size();
 }
 public static void backtrack(int row, int NumOfQueen, List<List<String>> res, ArrayList<String> tmplist, List<Integer> col, List<Integer> z_diagonal, List<Integer> f_diagonal) {
     //到达了最后一行
     if (row == NumOfQueen) {
         res.add(new ArrayList<>(tmplist));
         return;
     }
     //从第0列开始遍历
     for (int column = 0; column < NumOfQueen; column++) {
         //如果不在攻击范围内(不在同一行或者同一列 && 负对角线和相等 &&  正对角线差相等)
         if (!col.contains(column) && !f_diagonal.contains(row + column) && !z_diagonal.contains(row - column)) {
             col.add(column);
             f_diagonal.add(row + column);
             z_diagonal.add(row - column);
             char[] s = new char[NumOfQueen];
             Arrays.fill(s, '.');
             //这一行的j位置放皇后
             s[column] = 'Q';
             tmplist.add(new String(s));
             //回溯算法
             backtrack(row+1,NumOfQueen,res,tmplist,col,z_diagonal,f_diagonal);
             tmplist.remove(tmplist.size() - 1);
             col.remove(Integer.valueOf(column));
             f_diagonal.remove(Integer.valueOf(row + column));
             z_diagonal.remove(Integer.valueOf(row - column));
         }
     }
  }
}

leetcode_【78】子集I

https://leetcode-cn.com/problems/subsets/

 给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
 说明:解集不能包含重复的子集。
 示例:
输入:
  nums = [1,2,3]
输出:
   [
   [3],
   [1],
   [2],
   [1,2,3],
   [1,3],
   [2,3],
   [1,2],
   []
   ]

代码

//执行用时 :2 ms, 在所有 Java 提交中击败了87.86%的用户
//内存消耗 :37 MB, 在所有 Java 提交中击败了44.12%的用户
class Solution {
     public static List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        backTrace(nums,0,new ArrayList<>(),res);
        return res;
    }

    private static void backTrace(int[] nums, int start, ArrayList<Integer> tmplist, List<List<Integer>> res) {
        res.add(new ArrayList<>(tmplist));
        for(int i = start;i<nums.length;i++){
            tmplist.add(nums[i]);
            backTrace(nums,i+1,tmplist,res);
            tmplist.remove(tmplist.size()-1);
        }
    }
}

leetcode_【90】子集 II

https://leetcode-cn.com/problems/subsets-ii/

给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
输入:
  [1,2,2]
输出:
    [
    [2],
    [1],
    [1,2,2],
    [2,2],
    [1,2],
    []
    ]

代码

//执行用时 :3 ms, 在所有 Java 提交中击败了87.52%的用户
//内存消耗 :38.5 MB, 在所有 Java 提交中击败了47.42%的用户
class Solution {
      public static List<List<Integer>> subsetsWithDup(int[] nums) {
        List<List<Integer>> res = new ArrayList<>();
        Arrays.sort(nums);
        backTrace(nums,0,new ArrayList<>(),res);
        return res;
    }
    private static void backTrace(int[] nums, int start, ArrayList<Integer> tmplist, List<List<Integer>> res) {
        res.add(new ArrayList<>(tmplist));
        for(int i = start;i<nums.length;i++){
            //和上一个数字相等则跳过
            if(i > start && nums[i] == nums[i-1] ){
                continue;
            }else{
                tmplist.add(nums[i]);
                backTrace(nums,i+1,tmplist,res);
                tmplist.remove(tmplist.size()-1);
            }

        }
    }
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值