首页 > 其他分享 >力扣77 组合

力扣77 组合

时间:2023-02-28 20:47:11浏览次数:31  
标签:77 组合 int res 个数 力扣 new path size

题目:

给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。
你可以按 任何顺序 返回答案。

示例:

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

思路:

  要解决 n为100,k为50的情况,暴力写法需要嵌套50层for循环,那么回溯法就用递归来解决嵌套层数的问题。递归来做层叠嵌套(可以理解是开k层for循环),每一次的递归中嵌套一个for循环,那么递归就可以用于解决多层嵌套循环的问题了

  每次从集合中选取元素,可选择的范围随着选择的进行而收缩,调整可选择的范围图中可以发现n相当于树的宽度,k相当于树的深度图中每次搜索到了叶子节点,我们就找到了一个结果。相当于只需要把达到叶子节点的结果收集起来,就可以求得 n个数中k个数的组合集合。

class Solution {
    //组合问题:N个数里面按一定规则找出k个数的集合
    List<List<Integer>> res=new ArrayList<>();
    LinkedList<Integer> path=new LinkedList<>();
    public List<List<Integer>> combine(int n, int k) {
        combineback(n,k,1);
        return res;
    }

    //1.回溯函数模板返回值以及参数
    public void combineback(int n,int k, int startIndex){
        //2.回溯函数终止条件
        if(path.size()==k){//找到叶子节点
            res.add(new ArrayList<>(path));
            //res.add(new ArrayList(path)):开辟一个独立地址,地址中存放的内容为path集合,后续path的变化不会影响到res。
            //res.add(path):将res尾部指向了path地址,后续path内容的变化会导致res的变化。
            return;
        }
        //3.回溯搜索的遍历过程
        for(int i=startIndex;i<=n;i++){
            path.add(i);//处理节点
            combineback(n, k, i + 1);//递归
            path.removeLast();//回溯,撤销处理结果
        }
    }
}

剪枝处理

  看一下优化过程如下:

  1. 已经选择的元素个数:path.size();

  2. 还需要的元素个数为: k - path.size();

  3. 在集合n中至多要从该起始位置 : n - (k - path.size()) + 1,开始遍历

  为什么有个+1呢,因为包括起始位置,我们要是一个左闭的集合。

遍历部分可改为:

for (int i=startIndex;i<=n-(k-path.size())+1;i++){
    path.add(i);
    combineHelper(n, k, i + 1);
    path.removeLast();
}

 

标签:77,组合,int,res,个数,力扣,new,path,size
From: https://www.cnblogs.com/cjhtxdy/p/17165896.html

相关文章

  • 组合数学笔记-排列与组合
    目录排列与组合排列排列的定义与基本性质错位排列错位排列的定义与基本性质圆排列圆排列的定义与基本性质多重集排列多重集排列的定义与基本性质组合组合的定义与基本性质......
  • 组合数学笔记-计数原理
    目录计数原理基本计数原理加法原理(分类)乘法原理(分步)减法原理(正难则反)除法原理(等价划分)重要计数原理抽屉原理(鸽巢原理)容斥原理约定:本笔记涉及的一切变量,若未特殊指明,则默......
  • 「组合数学」二:排列与组合
    四个基本计数原理四原理之外:一个非常基础的原理,全体等于各部分之和设\(S\)是集合,集合\(S\)的一个划分是满足下面条件的\(S\)的子集\(S_1,S_2,…,S_m\)的集合,即使得\(S\)......
  • 力扣---33. 搜索旋转排序数组
    整数数组nums按升序排列,数组中的值互不相同。在传递给函数之前,nums在预先未知的某个下标k(0<=k<nums.length)上进行了旋转,使数组变为[nums[k],nums[k+1],...,......
  • 力扣---2363. 合并相似的物品
    给你两个二维整数数组items1和items2,表示两个物品集合。每个数组items有以下特质:   items[i]=[valuei,weighti]其中valuei表示第i件物品的价值,weighti......
  • Codeforces Round #776 (Div
    CodeforcesRound#776(Div.3)CodeForces-1650DTwistthePermutation给定你数组a:123...n,一共有n次操作,每次操作可以把\(a_i\)移到最左边,然后对\(i+1\)位以......
  • 代码随想录算法Day27 | 39. 组合总和 , 40.组合总和II ,131.分割回文串
    39.组合总和题目链接:39.组合总和-力扣(LeetCode)思路既然题目说可以数组中的数可以无限制重复被选取,那么说明在选取该元素的下一个分支也可以继续使用。选取和剪枝过......
  • 代码随想录训练营day 2 |977有序数组的平方 209.长度最小的子数组 (C++)
    977、有序数组的平方题目链接:977、有序数组的平方题目描述:给你一个按非递减顺序排序的整数数组nums,返回每个数字的平方组成的新数组,要求也按非递减顺序排序。例......
  • 力扣1049 最后一块石头的重量2
    题目:有一堆石头,用整数数组stones表示。其中stones[i]表示第i块石头的重量。每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为x和y,且x<=......
  • day77-todolist案例
    todolist案例总和设计一个添加删除框,添加代办的事项,外加一个勾选框可以一键删除所有已完成的事项初期设计首先设计静态功能:分为头部中间尾部三部分头部一个添......