力扣大厂热门面试算法题 39-41

39. 组合总和,40. 组合总和 II,41. 缺失的第一个正数,每题做详细思路梳理,配套Python&Java双语代码, 2024.03.17 可通过leetcode所有测试用例。

目录

39. 组合总和

解题思路

完整代码

Python

Java

40. 组合总和 II

解题思路

完整代码

Python

Java

41. 缺失的第一个正数

解题思路

完整代码

Python

Java


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 <= candidates.length <= 30
  • 2 <= candidates[i] <= 40
  • candidates 的所有元素 互不相同
  • 1 <= target <= 40

解题思路

        对于这个问题,我们可以从空解开始,尝试每一个 candidates 中的数字,看它是否能够构成目标和。如果当前选择的数字和之前选择的数字的总和小于目标 target,我们可以继续选择相同的数字或下一个数字,因为题目中说明了同一个数字可以无限次重复选择。如果总和等于目标 target,则将当前解添加到结果列表中。如果总和大于 target,则回溯,尝试下一个数字。

解题步骤如下:

  1. candidates 进行排序,以便我们可以在总和超过 target 时提前终止搜索。
  2. 使用回溯法构建一个辅助函数来生成所有可能的组合。这个函数将会接收当前的组合、当前的总和、当前位置和目标 target
  3. 在每次调用中,如果当前总和等于目标 target,则将当前组合添加到结果列表中。如果当前总和大于 target,则终止当前分支。
  4. 从当前位置开始,递归地尝试每一个可能的选项,将当前数字添加到当前组合中,并更新当前总和。每次递归调用后,撤销上一次选择,以尝试下一个数字。
  5. 最终返回结果列表。

完整代码

Python
class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        def backtrack(start, path, target):
            if target == 0:
                result.append(list(path))
                return
            if target < 0:
                return
            for i in range(start, len(candidates)):
                path.append(candidates[i])
                backtrack(i, path, target - candidates[i])  # 不增加i的值来允许数字重复选择
                path.pop()  # 回溯

        result = []
        candidates.sort()  # 排序有助于提前终止搜索
        backtrack(0, [], target)
        return result
Java
public class Solution {
    public List<List<Integer>> combinationSum(int[] candidates, int target) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(candidates); // 排序有助于提前终止搜索
        backtrack(result, new ArrayList<>(), candidates, target, 0);
        return result;
    }

    private void backtrack(List<List<Integer>> result, List<Integer> tempList, int[] candidates, int remain, int start) {
        if (remain == 0) {
            result.add(new ArrayList<>(tempList));
        } else if (remain < 0) {
            return;
        } else {
            for (int i = start; i < candidates.length; i++) {
                tempList.add(candidates[i]);
                backtrack(result, tempList, candidates, remain - candidates[i], i); // 不增加i的值来允许数字重复选择
                tempList.remove(tempList.size() - 1); // 回溯
            }
        }
    }
}

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 <= candidates.length <= 100
  • 1 <= candidates[i] <= 50
  • 1 <= target <= 30

解题思路

这个问题与之前的问题类似,但有一个关键的区别:每个数字在每个组合中只能使用一次。我们仍然可以使用回溯法来解决这个问题,但需要添加一些额外的步骤来确保不会有重复的组合。

解题步骤如下:

  1. candidates 进行排序,这样有助于我们在递归时跳过重复的数字,以避免产生重复的组合。
  2. 使用回溯法构建一个辅助函数来生成所有可能的组合。这个函数将会接收当前的组合、当前的总和、当前位置和目标 target
  3. 在每次调用中,如果当前总和等于目标 target,则将当前组合添加到结果列表中。如果当前总和大于 target,则终止当前分支。
  4. 从当前位置的下一个位置开始,递归地尝试每一个可能的选项,将当前数字添加到当前组合中,并更新当前总和。这一步确保了每个数字在每个组合中只使用一次。
  5. 为了避免重复的组合,每次在递归的同一层级中,如果遇到与之前相同的数字,则跳过这个数字。
  6. 每次递归调用后,撤销上一次选择,以尝试下一个数字。
  7. 最终返回结果列表。

完整代码

Python
class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        def backtrack(start, path, target):
            if target == 0:
                result.append(list(path))
                return
            if target < 0:
                return
            for i in range(start, len(candidates)):
                if i > start and candidates[i] == candidates[i - 1]:
                    continue  # 跳过重复的数字
                path.append(candidates[i])
                backtrack(i + 1, path, target - candidates[i])  # i + 1 确保每个数字只用一次
                path.pop()  # 回溯

        result = []
        candidates.sort()  # 排序有助于提前终止搜索
        backtrack(0, [], target)
        return result
Java
public class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(candidates); // 排序有助于提前终止搜索
        backtrack(result, new ArrayList<>(), candidates, target, 0);
        return result;
    }

    private void backtrack(List<List<Integer>> result, List<Integer> tempList, int[] candidates, int remain, int start) {
        if (remain == 0) {
            result.add(new ArrayList<>(tempList));
        } else if (remain < 0) {
            return;
        } else {
            for (int i = start; i < candidates.length; i++) {
                if (i > start && candidates[i] == candidates[i - 1]) continue; // 跳过重复的数字
                tempList.add(candidates[i]);
                backtrack(result, tempList, candidates, remain - candidates[i], i + 1); // i + 1 确保每个数字只用一次
                tempList.remove(tempList.size() - 1); // 回溯
            }
        }
    }
}

41. 缺失的第一个正数

给你一个未排序的整数数组 nums ,请你找出其中没有出现的最小的正整数。

请你实现时间复杂度为  O(n) 并且只使用常数级别额外空间的解决方案。

示例 1:

输入:nums = [1,2,0]
输出:3
解释:范围 [1,2] 中的数字都在数组中。

示例 2:

输入:nums = [3,4,-1,1]
输出:2
解释:1 在数组中,但 2 没有。

示例 3:

输入:nums = [7,8,9,11,12]
输出:1
解释:最小的正数 1 没有出现。

解题思路

        这个问题可以通过 "原地哈希" 的方式来解决。原地哈希通常指的是直接在输入数组上进行操作,而不使用额外的空间来存储数据。由于我们只关心最小的未出现的正整数,我们可以尝试将数组中所有的正整数 n 放到数组的 n-1 位置上。这样,如果数组是完全按顺序的(即 nums[i] = i + 1),我们就知道数组中包含了所有从 1n 的正整数,因此未出现的最小正整数就是 n + 1

解题步骤如下:

  1. 遍历数组,对于每个数字,如果它在 1n 的范围内,并且它不在正确的位置上(即 nums[i] != nums[nums[i] - 1]),则将其与正确位置上的数字交换。这个步骤可能需要多次交换才能将一个数字放到正确的位置。
  2. 再次遍历数组,第一个不满足 nums[i] = i + 1 的位置 i,其对应的最小未出现正整数就是 i + 1
  3. 如果所有位置都满足 nums[i] = i + 1,则数组中的最小未出现的正整数是 n + 1

完整代码

Python
class Solution:
    def firstMissingPositive(self, nums: List[int]) -> int:
        n = len(nums)
        for i in range(n):
            while 1 <= nums[i] <= n and nums[nums[i] - 1] != nums[i]:
                nums[nums[i] - 1], nums[i] = nums[i], nums[nums[i] - 1]
        
        for i in range(n):
            if nums[i] != i + 1:
                return i + 1
        return n + 1
Java
public class Solution {
    public int firstMissingPositive(int[] nums) {
        int n = nums.length;
        for (int i = 0; i < n; i++) {
            while (nums[i] > 0 && nums[i] <= n && nums[nums[i] - 1] != nums[i]) {
                int temp = nums[nums[i] - 1];
                nums[nums[i] - 1] = nums[i];
                nums[i] = temp;
            }
        }

        for (int i = 0; i < n; i++) {
            if (nums[i] != i + 1) {
                return i + 1;
            }
        }
        return n + 1;
    }
}

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

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

相关文章

前端应用开发实验:Vue的特性

目录 实验目的实验内容图片浏览功能代码实现效果 简单购物车功能代码实现效果 汇率换算功能代码实现效果 关于需要准备的内容&#xff0c;如Vue的下载就不多赘述了 实验目的 &#xff08;1&#xff09;掌握vue实例编写的语法和基本选项的使用 &#xff08;2&#xff09;在实际…

深度学习pytorch——Broadcast自动扩展

介绍 在 PyTorch 中&#xff0c;Broadcast 是指自动扩展&#xff08;broadcasting&#xff09;运算的功能。它允许用户在不同形状的张量之间执行运算&#xff0c;而无需手动将它们的形状改变为相同的大小。当进行运算时&#xff0c;PyTorch 会自动调整张量的形状&#xff0c;使…

十八、软考-系统架构设计师笔记-真题解析-2022年真题

软考-系统架构设计师-2022年上午选择题真题 考试时间 8:30 ~ 11:00 150分钟 1.云计算服务体系结构如下图所示&#xff0c;图中①、②、③分别与SaaS、PaaS、IaaS相对应&#xff0c;图中①、②、③应为( )。 A.应用层、基础设施层、平台层 B.应用层、平台层、基础设施层 C.平…

尊嘟假嘟,只需HiFi测序即可获得T2T基因组?

探秘动植物物种进化及遗传多样性的第一步往往是进行基因组测序&#xff0c;基因组从头组装&#xff08;Genome De novo assembly&#xff09; 是指从测序数据中重建生物基因组序列的过程。组装一直是生物信息学中的核心问题。 然而&#xff0c;到2019年底完成图这个概念仍然只…

香港公司变更注册地址所需材料及流程全解析

香港公司变更注册地址&#xff1a;所需材料及流程全解析 各位老板好&#xff0c;我是经典世纪胡云帅&#xff0c;随着业务的拓展和发展&#xff0c;香港公司可能需要变更其注册地址。变更注册地址不仅关系到公司的日常运营&#xff0c;还与公司的法律地位和品牌形象息息相关。本…

Grok-1 开源:马斯克旗下xAI公司发布革命性AI模型,开启开源大模型新篇章|3140亿参数

自从埃隆马斯克&#xff08;Elon Musk&#xff09;上周&#xff08;3月11日&#xff09;在 X 平台上宣布 Grok 将于本周开源的消息后&#xff0c;无数目光便聚焦于此&#xff0c;期待之情溢于言表。继 Meta 旗下的 Llama 2 模型开源之后&#xff0c;开源大模型界便充满了对新技…

Linux查看硬件型号详细信息

1.查看CPU &#xff08;1&#xff09;使用cat /proc/cpuinfo或lscpu &#xff08;2&#xff09;使用dmidecode -i processor Dmidecode 这款软件允许你在 Linux 系统下获取有关硬件方面的信息。Dmidecode 遵循 SMBIOS/DMI 标准&#xff0c;其输出的信息包括 BIOS、系统、主板、…

【Unity】获取游戏对象或组件的常用方法

前言 在Unity开发过程中&#xff0c;我们经常需要获取组件&#xff0c;那么在Unity里如何获取组件呢&#xff1f; 一、获取游戏对象 1.GameObject.Find GameObject.Find 是通过物体的名称获取对象的 所以会遍历当前整个场景&#xff0c;效率较低 而且只能获取激活状态的物体…

Sentinel篇:线程隔离和熔断降级

书接上回&#xff1a;微服务&#xff1a;Sentinel篇 3. 隔离和降级 限流是一种预防措施&#xff0c;虽然限流可以尽量避免因高并发而引起的服务故障&#xff0c;但服务还会因为其它原因而故障。 而要将这些故障控制在一定范围&#xff0c;避免雪崩&#xff0c;就要靠线程隔离…

作品展示ETL

1、ETL 作业定义、作业导入、控件拖拽、执行、监控、稽核、告警、报告导出、定时设定 欧洲某国电信系统数据割接作业定义中文页面&#xff08;作业顶层&#xff0c;可切英文&#xff0c;按F1弹当前页面帮助&#xff09; 涉及文件拆分、文件到mysql、库到库、数据清洗、数据转…

青海200MW光伏项目 35kV开关站图像监控及安全警示系统

一、背景 随着我国新能源产业的快速发展&#xff0c;光伏发电作为清洁能源的重要组成部分&#xff0c;得到了国家政策的大力扶持。青海作为我国光伏资源丰富地区&#xff0c;吸引了众多光伏项目的投资建设。在此背景下&#xff0c;为提高光伏发电项目的运行效率和安全性能&…

数据安全与个人隐私:美国人的焦虑与变化

PrimiHub一款由密码学专家团队打造的开源隐私计算平台&#xff0c;专注于分享数据安全、密码学、联邦学习、同态加密等隐私计算领域的技术和内容。 在这个每一次点击、轻敲或按键都留下数字踪迹的时代&#xff0c;美国人对个人数据安全的焦虑与日俱增。他们感觉对数据的使用几乎…

R语言:microeco:一个用于微生物群落生态学数据挖掘的R包,第四:trans_beta class

trans_beta class&#xff1a;利用trans_beta类可以变换和绘制beta分集的距离矩阵。该类中涉及到beta多样性的分析主要包括排序、群距、聚类和方差分析。我们首先使用PCoA显示排序。 > dataset$cal_betadiv() The result is stored in object$beta_diversity ... > t1 &…

unittest初级了解

unitttest初级了解 单元测试框架测试流程 编写测试用例创建测试类测试用例测试用例执行 单元测试框架 unittest(python自带的)&#xff0c;pytest(第三方库) 测试流程 编写测试用例—收集测试用例—执行用例—生成测试结果 编写测试用例 创建测试类 类名称建议以Test开头&…

html系列:按钮被样式图片挡着了,无法点击怎么办

​ 背景 在开发中会遇到一些奇奇怪怪的需求&#xff0c;比如在按钮上要显示一个样式图片&#xff0c;同时还要能不影响按钮的点击使用&#xff1b;这时候&#xff0c;设置好了样式&#xff0c;按钮无法点击怎么办&#xff1f; 在查阅资料的时候找到了解决方案。 解决方案 …

WPF图表库LiveCharts的使用

这个LiveCharts非常考究版本&#xff0c;它有非常多个版本&#xff0c;.net6对应的是LiveChart2 我这里的wpf项目是.net6&#xff0c;所以安装的是这三个&#xff0c;搜索的时候要将按钮“包括愈发行版”打勾 git&#xff1a;https://github.com/beto-rodriguez/LiveCharts2?…

数学建模——蒙特卡洛法

目录 1.介绍2.可以做的题型3.实战3.1求pi的值3.2求定积分x^2 的值 参加了大大小小很多场比赛了&#xff0c;但是都是混子&#xff0c;但还是打算记录一下吧&#xff0c;系统认真过一遍。后续功力深厚&#xff0c;会拓展写的文章&#xff0c;目前是干货&#xff0c;一些背景啥的…

2024 年(第 12 届)“泰迪杯”数据挖掘挑战赛—— C 题:竞赛论文的辅助自动评阅完整思路与源代码分享

一、问题背景 近年来我国各领域各层次学科竞赛百花齐放&#xff0c;层出不穷&#xff0c;学生参与度也越来越高。随着参赛队伍的增 加&#xff0c;评阅论文的工作量急剧增加&#xff0c;这对评阅论文的人力要求也越来越大。因此引入机器辅助评阅成为竞赛主办方的现实需求。 在…

System Verilog的接口、程序块与断言解析

接口、程序块与断言 1 接口 1.1 使用接口简化连接 // 接口 interface arb_if(input bit clk);logic [1:0] grant,request;logic rst; endinterface// 使用了简单接口的仲裁器 module arb (arb_if arbif);...always(posedge arbif.clk or posedge arbif.rst)beginif(arbif.rs…

计算方法实验1:圆形镜面成像问题

Algorithm Description 设 T ( c o s θ , s i n θ ) T(cos\theta,sin\theta) T(cosθ,sinθ),则有 P T Q T ( P x − c o s θ ) 2 s i n 2 θ ( Q x − c o s θ ) 2 ( Q y − s i n θ ) 2 PTQT\sqrt{(P_x-cos\theta)^2sin^2\theta}\sqrt{(Q_x-cos\theta)^2(Q_y-sin…