• 数字组合问题:Combination,CombinationSum,CombinationSum2,CombinationSum3


    Combination问题描述:给定n和k,找出1-n之间所有k个数的组合,例如:n=3,k=2,返回

    [[1,2]  [1,3]  [2,3]]

    算法分析:利用递归。递归边界就是curr.size()==k。

     1 public List<List<Integer>> combine(int n, int k)
     2     {
     3         List<List<Integer>> result = new ArrayList<>();
     4         List<Integer> current = new ArrayList<>();
     5         if(n <= 0 || n<k)
     6         {
     7             return result;
     8         }
     9         combine(n, k, 1, current, result);
    10         return result;
    11     }
    12     //递归和n,k无关,只是边界条件和k相关,n,k在递归中不变化。
    13     public void combine(int n, int k, int start, List<Integer> current, List<List<Integer>> result)
    14     {
    15         if(current.size() == k)
    16         {
    17             List<Integer> temp = new ArrayList<>(current);
    18             result.add(temp);
    19             return ;
    20         }
    21         for(int i = start; i <= n; i ++)
    22         {
    23             current.add(i);
    24             combine(n, k, i+1, current, result);
    25             current.remove(current.size()-1);
    26         }
    27     }

    CombinationSum问题描述:给一组数字和target,这组数字没有重复元素,找出这组数字中相加为target的集合。

    例如给定set[2,3,6,7]和target=7.返回[[7]  [2,2,3]]. 也就是说,数字集合没有重复,但是结果集里面可以重复某个元素。先把数据集排序。

    算法分析:利用递归,边界条件是target==0.

     1 public List<List<Integer>> combinationSum(int[] candidates, int target) 
     2     {
     3         List<List<Integer>> result = new ArrayList<>();
     4         List<Integer> current = new ArrayList<>();
     5         if(candidates == null || candidates.length == 0)
     6         {
     7             return result;
     8         }
     9         Arrays.sort(candidates);
    10         combinationSum(candidates, target, 0, current, result);
    11         return result;
    12     }
    13     
    14     public void  combinationSum(int[] candidates, int target, int i, List<Integer> curr, List<List<Integer>> result)
    15     {
    16         if(target == 0)//组合成功
    17         {
    18             List<Integer> temp = new ArrayList<>(curr);
    19             result.add(temp);
    20             return;
    21         }
    22         for(int j = i; j < candidates.length; j ++)
    23         {
    24             if(target < candidates[j])
    25             {
    26                 return ;
    27             }
    28             curr.add(candidates[j]);
    29             combinationSum(candidates, target-candidates[j], j, curr, result);
    30             //如果上一步递归返回则去掉最后加入的元素,然后回溯。
    31             //curr.remove(candidates[j]);错误,list的参数是index
    32             curr.remove(curr.size()-1);
    33         }
    34     }

    CombinationSum2问题描述:给定数据集里面有重复元素,但是结果集中每个数据集中的元素只能出现一次。

    例如:[10, 1, 2, 7, 6, 1, 5],target=8,返回 17  125 26 116

    算法分析:递归的下标要取j+1,然后还要过滤相同序列。使用hashset。

     1 public List<List<Integer>> combinationSum2(int[] candidates, int target) {
     2         List<List<Integer>> result = new ArrayList<>();
     3         List<Integer> current = new ArrayList<>();
     4         if(candidates == null || candidates.length == 0)
     5         {
     6             return result;
     7         }
     8         Arrays.sort(candidates);
     9         combinationSum2(candidates, target, 0, current, result);
    10         //利用hashset过滤重复元素
    11         HashSet<List<Integer>> set = new HashSet<>(result);
    12         result.clear();
    13         result.addAll(set);
    14         return result;
    15     }
    16     
    17     public void combinationSum2(int[] candidates, int target, int i, List<Integer> curr, List<List<Integer>> result)
    18     {
    19         if(target == 0)
    20         {
    21             List<Integer> temp = new ArrayList<>(curr);
    22             result.add(temp);
    23             return;
    24         }
    25         for(int j = i; j < candidates.length; j ++)
    26         {
    27             if(candidates[j] > target)
    28             {
    29                 return;
    30             }
    31             curr.add(candidates[j]);
    32             //下标j+1,过滤相同元素
    33             combinationSum2(candidates, target-candidates[j], j + 1, curr, result);
    34             curr.remove(curr.size()-1);
    35         }
    36     }

    CombinationSum3:给定k和target,找到1-9集合中满足k个数的和=target的序列集合。

    例如:k=3,target=6.返回123 , k=3, target=9,返回126,135,234

    算法分析:这道题和3Sum很像,因为3Sum不能用递归,因为时间复杂度太高。还有一类问题,就是说i<j<k, 返回i,j,k,,满足i+j+k=target

    这种只能用三层for循环了,因为没有数据集的限制。

     1 public List<List<Integer>> combinationSum3(int k, int n) {
     2         List<List<Integer>> result = new ArrayList<>();
     3         List<Integer> curr = new ArrayList<>();
     4         combinationSum3(k, n, 1, curr, result);
     5         return result;
     6     }
     7     
     8     public void combinationSum3(int k, int target, int i, List<Integer> curr, List<List<Integer>> result)
     9     {
    10         if(curr.size() == k && target == 0)
    11         {
    12             result.add(new ArrayList<Integer>(curr));
    13             return;
    14         }
    15         
    16         for(int j = i; j <= 9; j ++)
    17         {
    18             if(target < j)
    19             {
    20                 return ;
    21             }
    22             curr.add(j);
    23             combinationSum3(k, target - j, j+1, curr, result);
    24             curr.remove(curr.size() - 1);
    25         }
    26     }
  • 相关阅读:
    图,深度,广度优先遍历(一)
    java实现快速排序
    图,深度,广度优先遍历(二)
    图,深度,广度优先遍历(三)
    Jpa动态多表if多条件联合查询(if中包含list不为null和“=”的判断),并对查询结果进行分页
    SpringBoo启动报错:Failed to load property source from location ‘classpath:/bootstrap.yml‘
    Java对象创建和Javabean创建
    Linux解压命令
    BDD测试利器:mocha+should.js
    《老码识途》读书笔记:第一章(中)
  • 原文地址:https://www.cnblogs.com/masterlibin/p/5600474.html
Copyright © 2020-2023  润新知