• 找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1


    找出所有相加之和为 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]]

     1 class Solution {
     2     public List<List<Integer>> combinationSum3(int k, int n) {
     3         List<List<Integer>> result = new ArrayList<>();
     4         for(int i=0;i < result.size();i++){
     5             List<Integer> list = new ArrayList<>();
     6             List<Integer> re = digui(i,list,n,k);
     7             if(re !=null){
     8                 result.add(re);
     9             }
    10         }
    11         return result;
    12     }
    13 
    14     List<Integer> digui(int c,List<Integer> a,int n,int k){
    15         int b;
    16         if(a.size() == 0){
    17             b = c;
    18             a.add(b);
    19             return digui(c,a,n,k);
    20         }else{
    21             b = a.get(a.size()-1)+1;
    22         }
    23         
    24         int total = 0;
    25         for(int aa:a){
    26             total +=aa;
    27         }
    28         if(total == n){
    29             return a;
    30         }
    31         if(b>9 || total > n ||a.size()>k)
    32             return null;
    33         a.add(b);
    34         return digui(c,a,n,k);
    35     }
    36 }

     递归不行,要使用回溯进行解决

     1 class Solution {
     2     //结果集
     3     public static List<List<Integer>> lists = new ArrayList<List<Integer>>();
     4     //临时集
     5     public static List<Integer> list = new ArrayList<Integer>();
     6     public List<List<Integer>> combinationSum3(int k, int n) {
     7         huisu(1,list,n,k,0,0);
     8         return lists;
     9     }
    10 
    11     void huisu(int c,List<Integer> a,int n,int k,int sum,int index){
    12         if(k>n){
    13             return;
    14         }
    15         if(index == k && sum == n){
    16             List<Integer> currentList = new ArrayList<Integer>();
    17             currentList.addAll(list);
    18             lists.add(currentList);
    19             return;
    20         }
    21 
    22         if(sum > n){
    23             return;
    24         }
    25         for(int i = c;i<= 9; ++i){
    26             list.add(i);
    27             sum+=i;
    28             huisu(i+1,list,n,k,sum,index+1);
    29             list.remove(list.size()-1);
    30             sum -=i;
    31         }
    32     }
    33 }

    递归和回溯的区别

    递归:程序调用自身的编程技巧。

      作为一种程序设计算法,有着广泛应用。需要注意的是,递归结束的条件要控制好。

    回溯:是一种算法思想,可以用递归来实现。

      回溯算法实际上一个类似枚举的搜索尝试过程,主要是在搜索尝试过程中寻找问题的解,当发现已不满足求解条件时,就"回溯"返回,尝试别的路径。

      回溯法是一种选优搜索法,按选优条件向前搜索,以达到目标。但当探索到某一步时,发现原先选择并不优或达不到目标,就退回一步重新选择,这种走不通就退回再走的技术为回溯法。

    回溯思路:

      基本如下:当前局面下,我们有若干种选择,所以我们对每一种选择进行尝试。如果发现某种选择违反了某些限定条件,此时 return;如果尝试某种选择到了最后,发现该选择是正确解,那么就将其加入到解集中。
      在这种思想下,我们需要清晰的找出三个要素:选择 (Options),限制 (Restraints),结束条件 (Termination)。

    回溯算法框架:

     1 result = []
     2 def backtrack(路径, 选择列表):
     3     if 满足结束条件:
     4         result.add(路径)
     5         return
     6     
     7     for 选择 in 选择列表:
     8         做选择
     9         backtrack(路径, 选择列表)
    10         撤销选择

    其核心就是 for 循环里面的递归,在递归调用之前「做选择」,在递归调用之后「撤销选择」,特别简单。

    递归与回溯的区别

    递归是一种算法结构。递归会出现在子程序中,形式上表现为直接或间接的自己调用自己。典型的例子是阶乘,计算规律为:n!=n×(n1)!

    回溯是一种算法思想,它是用递归实现的。回溯的过程类似于穷举法,但回溯有“剪枝”功能,即自我判断过程。例如有求和问题,给定有 7 个元素的组合 [1, 2, 3, 4, 5, 6, 7],求加和为 7 的子集。累加计算中,选择 1+2+3+4 时,判断得到结果为 10 大于 7,那么后面的 5, 6, 7 就没有必要计算了。这种方法属于搜索过程中的优化,即“剪枝”功能。

    用一个比较通俗的说法来解释递归和回溯:
    我们在路上走着,前面是一个多岔路口,因为我们并不知道应该走哪条路,所以我们需要尝试。尝试的过程就是一个函数。
    我们选择了一个方向,后来发现又有一个多岔路口,这时候又需要进行一次选择。所以我们需要在上一次尝试结果的基础上,再做一次尝试,即在函数内部再调用一次函数,这就是递归的过程。
    这样重复了若干次之后,发现这次选择的这条路走不通,这时候我们知道我们上一个路口选错了,所以我们要回到上一个路口重新选择其他路,这就是回溯的思想

    参考:https://www.cnblogs.com/fanguangdexiaoyuer/p/11224426.html

       https://blog.csdn.net/summer_dew/article/details/8392158

          https://blog.csdn.net/a1439775520/article/details/104539875

  • 相关阅读:
    Linux下文件属性(drwxr-xr-x)详解以及(-rwxrwxrwx=777)(转)
    Linux中chown和chmod的区别和用法(转)
    以root用户身份在jenkins中运行shell命令
    Java中Properties配置文件读取
    Java分布式服务框架Dubbo初探(待实践)
    Servlet3.0新特性
    Java中System.getProperty()的参数
    Java获取路径的方法分析详解(Application/Web)
    Java中的JAR/EAR/WAR包的文件夹结构说明(转)
    JAR包中的MANIFEST.MF文件详解以及编写规范
  • 原文地址:https://www.cnblogs.com/zluckiy/p/13653020.html
Copyright © 2020-2023  润新知