leetcode216.组合总和III、40.组合总和II、39.组合总和

216.组合总和III

找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:
只使用数字1到9
每个数字 最多使用一次
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

示例 1:
输入: k = 3, n = 7
输出: [[1,2,4]]
解释:
1 + 2 + 4 = 7
没有其他符合的组合了。

示例 2:
输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
解释:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
没有其他符合的组合了。

示例 3:
输入: k = 4, n = 1
输出: []
解释: 不存在有效的组合。
在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。

解题思路

本题就是在[1,2,3,4,5,6,7,8,9]这个集合中找到和为n的k个数的组合。
本题k相当于树的深度,9(因为整个集合就是9个数)就是树的宽度。

例如 k = 2,n = 4的话,就是在集合[1,2,3,4,5,6,7,8,9]中求 k(个数) = 2, n(和) = 4的组合。

选取过程如图:
在这里插入图片描述

回溯三部曲

1.确定递归函数参数

和77. 组合一样,依然需要一维数组path来存放符合条件的结果,二维数组result来存放结果集。
这里我依然定义path 和 result为全局变量。
至于为什么取名为path?从上面树形结构中,可以看出,结果其实就是一条根节点到叶子节点的路径。
接下来还需要如下参数:
n(int)目标和,也就是题目中的n。
k(int)就是题目中要求k个数的集合。
sum(int)为已经收集的元素的总和,也就是path里元素的总和。
startIndex(int)为下一层for循环搜索的起始位置。

2、确定终止条件

在上面已经说了,k其实就已经限制树的深度,因为就取k个元素,树再往下深了没有意义。
所以如果pathTop和 k相等了,就终止。
如果此时path里收集到的元素和(sum) 和n(就是题目描述的n)相同了,就用result收集当前的结果。
所以 终止代码如下:

if(pathTop==k){
        if(sum==n){
            int* tmp=(int*)malloc(sizeof(int)*k);
            for(int i=0;i<k;i++){
                tmp[i]=path[i];
            }
            ans[ansTop++]=tmp;
        }
        return;
    }
3、单层搜索过程

本题和77. 组合区别之一就是集合固定的就是9个数[1,…,9],所以for循环固定i<=9
在这里插入图片描述

for(int i=startIdx;i<=9;i++){
        sum+=i;
        path[pathTop++]=i;
         backtracking(n,k,sum,i+1);
          sum-=i;
          pathTop--;
    }

代码

未剪枝

int *path;
 int pathTop;
 int **ans;
 int ansTop;
 void backtracking(int n,int k,int sum,int startIdx){
    if(pathTop==k){
        if(sum==n){
            int* tmp=(int*)malloc(sizeof(int)*k);
            for(int i=0;i<k;i++){
                tmp[i]=path[i];
            }
            ans[ansTop++]=tmp;
        }
        return;
    }
    for(int i=startIdx;i<=9;i++){
        sum+=i;
        path[pathTop++]=i;
         backtracking(n,k,sum,i+1);
          sum-=i;
          pathTop--;
    }

 }
int** combinationSum3(int k, int n, int* returnSize, int** returnColumnSizes) {
    path=(int*)malloc(sizeof(int)*k);
    ans=(int**)malloc(sizeof(int*)*2000);
    pathTop=ansTop=0;
    backtracking(n,k,0,1);
    *returnSize=ansTop;
    *returnColumnSizes=(int*)malloc(sizeof(int)*ansTop);
    for(int i=0;i<ansTop;i++)
         (*returnColumnSizes)[i]=k;
        return ans;
}

剪枝

在这里插入图片描述

int *path;
 int pathTop;
 int **ans;
 int ansTop;
 void backtracking(int n,int k,int sum,int startIdx){
    if(sum>n) return;//剪枝,减去和大于n的分支
    if(pathTop==k){
        if(sum==n){
            int* tmp=(int*)malloc(sizeof(int)*k);
            for(int i=0;i<k;i++){
                tmp[i]=path[i];
            }
            ans[ansTop++]=tmp;
        }
        return;
    }
    for(int i=startIdx;i<=9-(k-pathTop)+1;i++){//剪枝,剪去不满足k个数的分支
        sum+=i;
        path[pathTop++]=i;
         backtracking(n,k,sum,i+1);
          sum-=i;
          pathTop--;
    }

 }
int** combinationSum3(int k, int n, int* returnSize, int** returnColumnSizes) {
    path=(int*)malloc(sizeof(int)*k);
    ans=(int**)malloc(sizeof(int*)*2000);
    pathTop=ansTop=0;
    backtracking(n,k,0,1);
    *returnSize=ansTop;
    *returnColumnSizes=(int*)malloc(sizeof(int)*ansTop);
    for(int i=0;i<ansTop;i++)
         (*returnColumnSizes)[i]=k;
        return ans;
}

40.组合总和II

给定一个可能有重复数字的整数数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用一次,解集不能包含重复的组合。

示例 1:
输入: candidates = [10,1,2,7,6,1,5], target = 8,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]

示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]

题目解析

元素在同一个组合内是可以重复的,怎么重复都没事,但两个组合不能相同。所以我们要去重的是同一树层上的“使用过”,同一树枝上的都是一个组合里的元素,不用去重。树层去重的话,需要对数组排序!

回溯三部曲

1、递归函数参数

和77. 组合一样,依然需要一维数组path来存放符合条件的结果,二维数组result来存放结果集。
这里我依然定义path 和 result为全局变量。length存放每个组合的长度。
至于为什么取名为path?从上面树形结构中,可以看出,结果其实就是一条根节点到叶子节点的路径。
接下来还需要如下参数:
target(int)目标和,也就是题目中的n。
candidates(int*)数组
candidatesSize(int)就是题目中数组的大小。
sum(int)为已经收集的元素的总和,也就是path里元素的总和。
startIndex(int)为下一层for循环搜索的起始位置。

2、递归终止条件

终止条件为 sum > target 和 sum == target。

3、单层搜索的逻辑

要去重的是“同一树层上的使用过”,如何判断同一树层上元素(相同的元素)是否使用过了呢。
如果candidates[i] == candidates[i - 1] 并且 i>starIdx,就说明:前一个树枝,使用了candidates[i - 1],也就是说同一树层使用过candidates[i - 1]。
此时for循环里就应该做continue的操作。

int *path;
 int pathTop;
 int **ans;
 int ansTop;
 int* length;
 int cmp(const void* a1, const void* a2) {
    return *((int*)a1) - *((int*)a2);
}
void backtracking(int* candidates,int candidatesSize,int target,int sum,int startIdx){
    if(sum>=target){
        if(sum==target){
            int* tmp=(int*)malloc(sizeof(int)*pathTop);
            for(int j=0;j<pathTop;j++)
            tmp[j]=path[j];
            length[ansTop]=pathTop;//存储当前组合的长度
             ans[ansTop++]=tmp;
        }
        return;
    }
    for(int i=startIdx;i<candidatesSize;i++){
        if(i>startIdx&&candidates[i]==candidates[i-1])continue;
        sum+=candidates[i];
        path[pathTop++]=candidates[i];
        backtracking(candidates,candidatesSize,target,sum,i+1);
        sum-=candidates[i];;
        pathTop--;
    }
}
int** combinationSum2(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes){
    path=(int*)malloc(sizeof(int)*50);
    ans=(int**)malloc(sizeof(int*)*100);
     length=(int*)malloc(sizeof(int)*100);
     ansTop=pathTop=0;
      qsort(candidates, candidatesSize, sizeof(int), cmp);
     backtracking(candidates,candidatesSize,target,0,0);
     *returnSize=ansTop;
    *returnColumnSizes=(int*)malloc(sizeof(int)*ansTop);
     for(int i=0;i<ansTop;i++)
     (*returnColumnSizes)[i]=length[i];
     return ans;
}

39.组合总和

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。

示例 1:
输入:candidates = [2,3,6,7], target = 7
输出:[[2,2,3],[7]]
解释:
2 和 3 可以形成一组候选,2 + 2 + 3 = 7 。注意 2 可以使用多次。
7 也是一个候选, 7 = 7 。
仅有这两种组合。

示例 2:
输入: candidates = [2,3,5], target = 8
输出: [[2,2,2,2],[2,3,3],[3,5]]

示例 3:
输入: candidates = [2], target = 1
输出: []

题目解析

在这里插入图片描述

回溯三部曲

1、递归函数参数

和77. 组合一样,依然需要一维数组path来存放符合条件的结果,二维数组result来存放结果集。
这里我依然定义path 和 result为全局变量。length存放每个组合的长度。
至于为什么取名为path?从上面树形结构中,可以看出,结果其实就是一条根节点到叶子节点的路径。
接下来还需要如下参数:
target(int)目标和,也就是题目中的n。
candidates(int*)数组
candidatesSize(int)就是题目中数组的大小。
sum(int)为已经收集的元素的总和,也就是path里元素的总和。
startIndex(int)为下一层for循环搜索的起始位置。

2、递归终止条件

终止条件为 sum > target 和 sum == target。

3、单层搜索的逻辑

单层for循环依然是从startIndex开始,搜索candidates集合。

int* path;
 int pathTop;
 int** ans;
 int ansTop;
 int* length;
void  backtarcking(int* candidates,int candidatesSize,int target,int sum,int startIdx){
    if(sum>=target){
        if(sum==target){
            int* tmp=(int*)malloc(sizeof(int)*pathTop);
            for(int i=0;i<pathTop;i++){
                tmp[i]=path[i];
            }
                length[ansTop]=pathTop;
                ans[ansTop++]=tmp;
            
        }
        return;
    }
    for(int i=startIdx;i<candidatesSize;i++){
        sum+=candidates[i];
        path[pathTop++]=candidates[i];
        backtarcking(candidates,candidatesSize,target,sum,i);
        sum-=candidates[i];
        pathTop--;
    }
}
int** combinationSum(int* candidates, int candidatesSize, int target, int* returnSize, int** returnColumnSizes) {
    path=(int*)malloc(sizeof(int)*50);
    ans=(int**)malloc(sizeof(int*)*200);
    length=(int*)malloc(sizeof(int)*200);
    pathTop=ansTop=0;
    backtarcking(candidates,candidatesSize,target,0,0);
    *returnSize=ansTop;
    *returnColumnSizes=(int*)malloc(sizeof(int)*ansTop);
    for(int i=0;i<ansTop;i++)
    (*returnColumnSizes)[i]=length[i];
    return ans;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/772777.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

百日筑基第十一天-看看SpringBoot

百日筑基第十一天-看看SpringBoot 创建项目 Spring 官方提供了 Spring Initializr 的方式来创建 Spring Boot 项目。网址如下&#xff1a; https://start.spring.io/ 打开后的界面如下&#xff1a; 可以将 Spring Initializr 看作是 Spring Boot 项目的初始化向导&#xff…

实训学习错误总结2

1、 "timestamp": "2024-07-04T08:43:07.15400:00", "status": 405, "error": "Method Not Allowed", "path": "/wuzi/insert" 简单的来说就是使用的方法与注释不匹配。 规定的是&#xff1a;Get&a…

第20章 Mac+VSCode配置C++环境

1. 下载VSCode VSCode下载地址在mac终端里输入xcode- select --install命令,根据提示安装xcode工具。2. 安装插件(4个) 打开VScode,点击应用右侧菜单栏 C/C++(必装) Code Runner(必装) CodeLLDB(代码调试),不安装这个插件程序调试时,无法在vscode自带的终端里输入参…

redis学习(002 安装redis和客户端)

黑马程序员Redis入门到实战教程&#xff0c;深度透析redis底层原理redis分布式锁企业解决方案黑马点评实战项目 总时长 42:48:00 共175P 此文章包含第5p-第p7的内容 文章目录 安装redis启动启动方式1&#xff1a;可执行文件启动启动方式2 基于配置文件启动修改redis配置文件 …

第四十七章 解决 IRIS 中的 SOAP 问题 - Web 网关中的 HTTP 跟踪

文章目录 第四十七章 解决 IRIS 中的 SOAP 问题 - Web 网关中的 HTTP 跟踪Web 网关中的 HTTP 跟踪第三方追踪工具 第四十七章 解决 IRIS 中的 SOAP 问题 - Web 网关中的 HTTP 跟踪 Web 网关中的 HTTP 跟踪 Web 网关管理页面可让跟踪 HTTP 请求和响应。请参阅使用 HTTP 跟踪工…

项目管理所需资料【资料分享】

项目管理基础知识 项目管理可分为五大过程组&#xff08;启动、规划执行、监控、收尾&#xff09;十大知识领域&#xff0c;其中包含49个子过程 项目十大知识领域分为&#xff1a;项目整合管理、项目范围管理、项目进度管理、项目成本管理、项目质量管理、项目资源管理、项目…

【BUUCTF-PWN】11-ciscn_2019_c_1

64位&#xff0c;开启了NX保护 执行效果如下&#xff1a; main函数 encrypt()函数 gets()函数存在栈溢出&#xff0c;但是中间部分代码会对传入的字符串做加密处理 中间的部分是对字符串进行处理&#xff0c;strlen的作用是得知字符串的长度&#xff0c;但是遇到’\0‘就…

C#委托事件的实现

1、事件 在C#中事件是一种特殊的委托类型&#xff0c;用于在对象之间提供一种基于观察者模式的通知机制。 1.1、事件的发送方定义了一个委托&#xff0c;委托类型的声明包含了事件的签名&#xff0c;即事件处理器方法的签名。 1.2、事件的订阅者可以通过运算符来注册事件处理器…

欧拉筛法与埃氏拉筛

如果我们想知道从零到一个数有哪些质数&#xff0c;我们首先会想到运用枚举法&#xff0c;将小于这个数的每个数都相乘一遍&#xff0c;这样的做法会大大降低我们程序的质数&#xff0c;增加时间&#xff0c;事实上&#xff0c;在我们之前就有许多人尝试运用另外的思维&#xf…

2pc 3pc

2pc&3pc问题 本质&#xff1a; 2pcTM超时机制 3pc加入事务询问机制RM超时机制 事务询问机制&#xff1a;减少阻塞 RM超时机制&#xff1a;避免死锁 2pc 3pc 参考&#xff1a; https://juejin.im/post/5aa3c7736fb9a028bb189bca#heading-1 https://blog.csdn.net/xj1…

【笔记】在window上连接虚拟机中的redis

愚昧啊 困扰了我近两天的问题居然是因为是java代码写错地方了 在虚拟机中进入redis.conf文件 vim redis.conf /bind --斜杠搜索关键词 将值设置为 bind 0.0.0.0 保存 退出:wq 回到java中 添加redis依赖 刷新maven 就是在这一步出问题……………………………………自己在蓝…

RK3568平台(opencv篇)ubuntu18.04上安装opencv环境

一.什么是 OpenCV-Python OpenCV-Python 是一个 Python 绑定库&#xff0c;旨在解决计算机视觉问题。   Python 是一种由 Guido van Rossum 开发的通用编程语言&#xff0c;它很快就变得非常流行&#xff0c;主要是 因为它的简单性和代码可读性。它使程序员能够用更少的代码行…

【踩坑】修复报错Cannot find DGL libdgl_sparse_pytorch_2.2.0.so

转载请注明出处&#xff1a;小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你&#xff0c;欢迎[点赞、收藏、关注]哦~ 目录 错误复现 原因分析 解决方法 错误复现 import dgldataset dgl.data.CoraGraphDataset() graph dataset[0] graph.adjacency_matrix() 原因分…

MySQL第二次作业

一、数据库 1、登陆数据库 2、创建数据库zoo 3、修改数据库zoo字符集为gbk 4、选择当前数据库为zoo 5、查看创建数据库zoo信息 6、删除数据库zoo 二、创建表 1、创建一个名称为db_system的数据库 2、在该数据库下创建两张表&#xff0c;具体要求如下 员工表 user 字段 类型 约…

阿里模型调用体验

引言 随着人工智能技术的飞速发展&#xff0c;大型模型已成为推动技术进步的关键因素之一。阿里大模型作为国内领先的人工智能技术之一&#xff0c;其在多个领域的应用展示了强大的潜力。本文将通过调用案例&#xff0c;简单解析阿里大模型在特定场景中的应用及其效果。 1.导…

面试知识储备-SpringCloud

1.为什么要出现springcloud? 单体架构 定义:传统的项目所有功能打成一个jar包就能直接部署,所有功能糅合到一起,非常简单 缺点:大公司项目某些功能的并发量大,会占用大量的资源,影响其他功能的正常运行(比如非常重要的交易功能) 微服务架构 定义:将各个功能拆分为独立项目…

云计算【第一阶段(26)】Linux网络设置

一、查看网络配置 1.查看网络接口信息ifconfig 查看所有活动的网络接口信息 2.ifconfig命令 查看指定网络接口信息 ifconfig 网络接口 &#xff08;1&#xff09;第一行&#xff1a;以太网卡的名字 ens33其中en代表以太网卡&#xff0c; centos6的是eth0&#xff0c; e…

TensorFlow安装CPU版本和GPU版本

文章目录 前言一、TensorFlow安装CPU版本1.新建虚拟环境2.激活虚拟环境3.下载tensorflow4.验证是否下载成功 二、TensorFlow安装GPU版本1.新建虚拟环境2.激活虚拟环境3.安装tensorflow-gpu4.验证是否下载成功 前言 下载的Anaconda是Anaconda3-2024.02-1-Windows-x86_64版本 一…

latex 报错解决①aligned ②begin document

1. 是aligned&#xff0c;不是align&#xff01;&#xff01; 网上写的公式大多是这样的 \begin{equation}\label{eq:2} \begin{align} Q\left( {s,t} \right) a{s^2} 2bst c{t^2} 2ds 2et f \end{align} \end{equation}但是报错&#xff1a; ! Package amsmath Erro…

大语言模型测评工具-ChatHub和ChatAll

背景 现在国内外拥有上百个大语言模型&#xff0c;在AI业务中&#xff0c;我们需要在其中选择一个合适业务模型&#xff0c;就需要对这些模型进行测试。手工去测试这么多模型效率一定不高&#xff0c;今天就介绍两个提高测评模型效率的工具 ChatHub和ChatAll。 介绍 ChatHub…