首页 > 编程语言 >代码随想录 | 回溯算法 ● 理论基础 ● 77. 组合

代码随想录 | 回溯算法 ● 理论基础 ● 77. 组合

时间:2023-10-07 21:02:50浏览次数:45  
标签:int 随想录 list 77 startIndex 回溯 new size

理论基础

  • 组合问题:N个数里面按一定规则找出k个数的集合(不强调顺序)
  • 切割问题:一个字符串按一定规则,有几种切割方式
  • 子集问题:一个N个数的集合里,有多少符合条件的子集
  • 排列问题:N个数按一定规则全排列,有几种排列方式(强调顺序)
  • 棋盘问题:N皇后,解数独等
回溯法模板
  • 回溯函数模板返回值以及参数

返回值一般为void

参数的确定比较困难,一般是需要什么参数,就填什么参数


  • 回溯函数终止条件

回溯函数一般用在树的结构上,当遍历到树的叶子节点,就找到了满足条件的一条答案,把这个答案存放起来,并结束本层循环。


  • 回溯搜索的遍历过程

回溯一般是在集合中递归搜索,集合的大小构成了树的宽度,递归的深度构成的树的深度,for循环就是遍历集合区间,可以理解一个节点有多少个孩子,这个for循环就执行多久。

代码随想录 | 回溯算法 ● 理论基础  ● 77. 组合_回溯

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }

    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}

第77题. 组合

力扣题目链接(opens new window)

给定两个整数 n 和 k,返回 1 ... n 中所有可能的 k 个数的组合。

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

解析:

可以按照上面的回溯方式,照猫画虎。首先,要知道这是个组合问题,那么就是没有顺序的,即[1,2]和[2,1]算是一种组合,而不是两种。

按照模板套的话即是如下的代码:

class Solution {
    List<Integer> list = new ArrayList<>();
    List<List<Integer>> result = new ArrayList<>();
    public List<List<Integer>> combine(int n, int k) {
        backTracking(n,k,1);
        return result;
    }
    void backTracking(int n, int k, int startIndex){
        if(list.size() == k){
            result.add(new ArrayList<>(list));
            return ;
        }
        for(int i = startIndex; i <= n; i++){
            list.add(i);
            backTracking(n,k,i+1);
            list.remove(list.size()-1);
        }
    }
}

优化:

剪枝操作,有点深,我是看了卡尔哥的视频,再结合底下“独舞鸾”的解析,才明白剪枝操作如何找边界。

首先,list.size(): 表示已经找到的个数

k-list.size(): 表示还需要找的个数

则[startIndex , n] 的数组长度起码应该是k - list.size() 才有可能继续搜索,则存在n - startIndex + 1 = k - list.size() , 则startIndex = n + 1 - (k-list.size()) , 也就是说startIndex 不能超过这个值。

class Solution {
    List<Integer> list = new ArrayList<>();
    List<List<Integer>> result = new ArrayList<>();
    public List<List<Integer>> combine(int n, int k) {
        backTracking(n,k,1);
        return result;
    }
    void backTracking(int n, int k, int startIndex){
        if(list.size() == k){
            result.add(new ArrayList<>(list));
            return ;
        }
        for(int i = startIndex; i <= n+1-k+list.size(); i++){
            list.add(i);
            backTracking(n,k,i+1);
            list.remove(list.size()-1);
        }
    }
}


标签:int,随想录,list,77,startIndex,回溯,new,size
From: https://blog.51cto.com/u_15505301/7742559

相关文章

  • 【二分】P7795 [COCI2014-2015#7] PROSJEK 题解
    P7795典。显然\(\mathcal{O}(n^2)\)的时间复杂度无法通过。使子段平均值最大,考虑二分。可以二分平均值\(mid\),然后判断是否有满足条件的子段.时间复杂度:\(\mathcal{O}(\dfrac{n\log\max\{a_i\}}{\text{eps}})\),其中\(\text{eps}\)为设置的精度,\(\max\{a_i\}\leq10......
  • P3477 [POI2008] PER-Permutation 解题报告
    我咕咕咕了这道题半年之久?好像洛谷好多题解都被hack了啊,但是没有被撤。(本题解现有hack均通过)题目链接折叠题干[POI2008]PER-Permutation题目描述Multisetisamathematicalobjectsimilartoaset,buteachmemberofamultisetmayhavemorethanonemem......
  • 随想录Day8|344. 反转字符串、541. 反转字符串Ⅱ、LCR 122. 路径加密、151. 反转字符
    随想录Day8|344.反转字符串、541.反转字符串Ⅱ、LCR122.路径加密、151.反转字符串里的单词、LCR182.动态口令 题目越来越长了…… 344.反转字符串文章&视频讲解编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组s的形式给出。不要给另外的数......
  • 代码随想录day21 | ● 530.二叉搜索树的最小绝对差 ● 501.二叉搜索树中的众数 ● 2
    530.二叉搜索树的最小绝对差classSolution{private:intresult=INT_MAX;TreeNode*pre=NULL;voidtraversal(TreeNode*cur){if(cur==NULL)return;traversal(cur->left);//左if(pre!=NULL){//中......
  • leetcode17、77
    回溯算法可以当作是二叉树的结构进行分析,看在叶节点的位置是什么条件收获结果每个抛进去的结果都是到叶子节点的路径以leetcode17为例:每一层遍历的是每一个号码对应的字符串,当号码全部遍历完成就可以返回结果,所以终止条件是(index==string.length());index是层数,string是号码。......
  • 随想录Day7|454. 四数相加Ⅱ、383. 赎金信、15. 三数之和、18. 四数之和
    随想录Day7|454.四数相加Ⅱ、383.赎金信、15.三数之和、18.四数之和 454.四数相加Ⅱ文章&视频讲解给你四个整数数组nums1、nums2、nums3和nums4,数组长度都是n,请你计算有多少个元组(i,j,k,l)能满足:0<=i,j,k,l<nnums1[i]+nums2[j]+nums3[k]+......
  • 随想录Day5|242. 有效的字母异位词、349. 两个数组的交集、202. 快乐数、1. 两数之和
    随想录Day5|242.有效的字母异位词、349.两个数组的交集、202.快乐数、1.两数之和 242.有效的字母异位词文章&视频讲解给定两个字符串s和t,编写一个函数来判断t是否是s的字母异位词。注意:若s和t中每个字符出现的次数都相同,则称s和t互为字母异位词。1......
  • ORA-04030: out of process memory when trying to allocate 27760032 bytes (qmxuPar
    1.alter日志2023-09-24T19:59:02.474578+08:00LOGMINER:Beginmininglogfileforsession-2147289087thread1sequence2185,+DATA/DB/ONLINELOG/redo05a.log2023-09-24T19:59:02.481095+08:00LOGMINER:Beginmininglogfileforsession-2147289087thread2sequence......
  • 代码随想录算法训练营-动态规划-2|62. 不同路径
    62. 不同路径 1classSolution:2defuniquePaths(self,m:int,n:int)->int:3#创建一个二维列表用于存储唯一路径数4dp=[[0]*nfor_inrange(m)]56#设置第一行和第一列的基本情况7foriinran......
  • CF877F 题解
    CF877F题解更好的阅读体验提供一个扫描线+根号分治做法。首先,可以把题目的条件转化成求$sum_r-sum_{l-1}=k$的区间数。考虑扫描线,当区间的右端点从$r-1$移动到$r$时,新增的区间的左端点就是所有满足$sum_{l-1}=sum_r-k,l\ler$的$l$。这时我们对$sum_{l-1}$......