【LeetCode热题100】打卡第16天:组合总和

news2024/10/9 8:28:11

文章目录

  • 组合总和
    • ⛅前言
    • 🔒题目
    • 🔑题解

组合总和

⛅前言

大家好,我是知识汲取者,欢迎来到我的LeetCode热题100刷题专栏!

精选 100 道力扣(LeetCode)上最热门的题目,适合初识算法与数据结构的新手和想要在短时间内高效提升的人,熟练掌握这 100 道题,你就已经具备了在代码世界通行的基本能力。在此专栏中,我们将会涵盖各种类型的算法题目,包括但不限于数组、链表、树、字典树、图、排序、搜索、动态规划等等,并会提供详细的解题思路以及Java代码实现。如果你也想刷题,不断提升自己,就请加入我们吧!QQ群号:827302436。我们共同监督打卡,一起学习,一起进步。

博客主页💖:知识汲取者的博客

LeetCode热题100专栏🚀:LeetCode热题100

Gitee地址📁:知识汲取者 (aghp) - Gitee.com

Github地址📁:Chinafrfq · GitHub

题目来源📢:LeetCode 热题 100 - 学习计划 - 力扣(LeetCode)全球极客挚爱的技术成长平台

PS:作者水平有限,如有错误或描述不当的地方,恳请及时告诉作者,作者将不胜感激

🔒题目

原题链接:39. 组合总和 - 力扣(LeetCode)

在这里插入图片描述

🔑题解

  • 解法一:回溯+剪枝

    这个解法,应该是最容易想到的,有一点比较肯,当满足题意的时候,一定要通过new一个新对象加入到ans中!

    在这里插入图片描述

    import java.util.*;
    import java.util.stream.Collectors;
    
    /**
     * @author ghp
     * @title 组合总和
     */
    class Solution {
        public List<List<Integer>> combinationSum(int[] candidates, int target) {
            List<List<Integer>> ans = new ArrayList<>(10);
            List<Integer> path = new ArrayList<>(10);
            dfs(ans, path, candidates, target);
            // 去重
            for (List<Integer> list : ans) {
                Collections.sort(list);
    
            }
            Set<List<Integer>> set = ans.stream().collect(Collectors.toSet());
            ans = new ArrayList<>(set);
            return ans;
        }
    
        private void dfs(List<List<Integer>> ans, List<Integer> path, int[] candidates, int target) {
            if (target < 0) {
                // 剪枝
                return;
            }
            if (target == 0) {
                // target==0,符合题意,直接将遍历的路径添加到ans中(一定要new一个新对象)
                ans.add(new ArrayList<>(path));
            }
            for (int i = 0; i < candidates.length; i++) {
                if (target - candidates[i] < 0){
                    // 当前不符合题意,直接下一个
                    continue;
                }
                target -= candidates[i];
                path.add(candidates[i]);
                dfs(ans, path, candidates, target);
                target += candidates[i];
                path.remove(path.size() - 1);
            }
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
    • 空间复杂度: O ( n ) O(n) O(n)

    其中 n n n 为数组中元素的个数

    备注:这里只是给出一个大概的时间复杂度(我估算的)

    在这里插入图片描述

    经过提交发现,在所有Java提交中,排名特别靠后,所以这段代码肯定是可以优化的,优化代码如下:

    这里主要有两个优化点:

    1. 数据结构的优化:原来的path是ArrayList,现在的path是Deque。因为Deque进行删除和新增操作的耗时要远远低于ArrayList(Deque删除和新增的时间复杂度是 O ( 1 ) O(1) O(1),而ArrayList的时间复杂度是 O ( n ) O(n) O(n)
    2. 剪枝优化:之前剪枝是在for循环外面实现的,剪枝不够彻底,会多遍历一层无用的数据。现在直接先对待遍历的元素进行排序,然后直接在for循环中进行剪枝,一下就提前将一些无用数据给剪枝了,这样剪枝更加彻底
    3. 代码逻辑优化:前面我们每次递归,都需要重新枚举所有元素的种类,现在我们每次递归都传递当前层,这样就能避免下次递归时,遍历到重复的元素了,从而有效避免了元素重复,也减少了去重的时间和空间损耗

    之前剪枝在for循环外面,会多遍历一层无用的数据,增加时间损耗:

    在这里插入图片描述

    import java.util.*;
    
    /**
     * @author ghp
     * @title 组合总和
     */
    class Solution {
        public List<List<Integer>> combinationSum(int[] candidates, int target) {
            List<List<Integer>> ans = new ArrayList<>(10);
            Deque<Integer> path = new LinkedList<>();
            // 对待选元素进行排序(升序),这是剪枝的前提
            Arrays.sort(candidates);
            dfs(ans, path, candidates, 0, target);
            return ans;
        }
    
        private void dfs(List<List<Integer>> ans, Deque<Integer> path, int[] candidates, int step, int target) {
            if (target == 0) {
                ans.add(new ArrayList<>(path));
                return;
            }
            for (int i = step; i < candidates.length; i++) {
                if (target - candidates[i] < 0) {
                    // 剪枝。当前i已经比target大了,那么i后面的肯定都要比target大
                    break;
                }
                path.addLast(candidates[i]);
                dfs(ans, path, candidates, i, target - candidates[i]);
                // 恢复现场,用于回溯
                path.removeLast();
            }
        }
    }
    

    优化后的代码,时间复杂度和前面的是一样的,但是却能够提前过滤掉许多数据,同时降低了递归的次数,不仅有效降低了时间损耗,也降低了空间损耗

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NmbigXUV-1686191441561)(D:/%E7%94%A8%E6%88%B7/ghp/Pictures/Typora/image-20230608101453910.png)]

  • 解法二:LeetCode官放提供的解法,回溯+剪枝

    import java.util.ArrayList;
    import java.util.Deque;
    import java.util.LinkedList;
    import java.util.List;
    
    /**
     * @author ghp
     * @title 组合总和
     */
    class Solution {
        public List<List<Integer>> combinationSum(int[] candidates, int target) {
            List<List<Integer>> ans = new ArrayList<>(10);
            Deque<Integer> path = new LinkedList<>();
            dfs(ans, candidates, target, path, 0);
            return ans;
        }
    
        public void dfs(List<List<Integer>> ans, int[] candidates, int target, Deque<Integer> path, int step) {
            if (step == candidates.length) {
                // 遍历到最底层了还没有发现
                return;
            }
            if (target == 0) {
                ans.add(new ArrayList<>(path));
                return;
            }
            // 直接遍历下一层
            dfs(ans, candidates, target, path, step + 1);
            // 遍历当前层
            if (target - candidates[step] >= 0) {
                // 这个if相当于进行一个筛选(也就是剪枝)
                path.addLast(candidates[step]);
                dfs(ans, candidates, target - candidates[step], path, step);
                path.removeLast();
            }
        }
    }
    

    复杂度分析:

    • 时间复杂度: O ( S ) O(S) O(S),S为所有可行解的长度之和
    • 空间复杂度: O ( t a r g e t ) O(target) O(target)

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Vue.js 中的 $router 和 $route

Vue.js 中的 $router 和 $route 在 Vue.js 中&#xff0c;$router 和 $route 是两个常用的对象&#xff0c;用于处理路由相关的操作。在本文中&#xff0c;我们将介绍 $router 和 $route 的区别&#xff0c;并且演示如何使用它们。 $router 和 $route 的区别 在 Vue.js 中&am…

Windows 下挂载使用 CephFS

一、Ceph集群搭建和CephFS创建 参考上期文章 Centos stream 8 使用 cephadm 安装 Ceph (17.2.6 quincy)集群_阿波罗.2012的博客-CSDN博客 二、将CephFS挂载到Windows Server 2019下 1、准备Dokany 下载地址&#xff1a;Release 1.5.1.1000 dokan-dev/dokany GitHub 下载…

【数据分享】1929-2022年全球站点的逐年平均降水量(Shp\Excel\12000个站点)

气象数据是在各项研究中都经常使用的数据&#xff0c;气象指标包括气温、风速、降水、湿度等指标&#xff0c;说到常用的降水数据&#xff0c;最详细的降水数据是具体到气象监测站点的降水数据&#xff01; 之前我们分享过1929-2022年全球气象站点的逐年平均气温数据、逐年最高…

实用工具篇(三):一款 IntelliJ IDEA 神级插件Bito

目录 1、什么是Bito 2、为什么要使用Bito 3、如何安装Bito插件 4、如何使用Bito插件 1、什么是Bito Bito是一款在IntelliJ IDEA编辑器中的插件&#xff0c;Bito插件是由ChatGPT团队开发的&#xff0c;它是ChatGPT团队为了提高开发效率而开发的一款工具。 Bito插件的强大…

Clion开发STM32之ESP8266系列(一)

系列开篇说明 结合个人的开发经验以及实际情况&#xff0c;分享stm32结合esp8266的一个开发项目。从0开始构建项目程序。为了方便记录项目开发记录&#xff0c;此系列的每个篇章都在git上做一个节点。此系列也是作为一个个人的开发思路和经验本次开发选用的芯片为stm32f103vet…

GIT安装教程(入门)

目录 前言 Git作者 官网 GIT优点 GIT缺点 为什么要使用 Git 下载以及安装步骤 一、官网下载 二、GIT安装步骤 GIT习题 习题一 总结 前言 Git 是一个分布式版本控制及源代码管理工具;Git 可以为你的项目保存若干快照&#xff0c;以此来对整个项目进行版本管理 Git作…

lan区段

LAN区段相当于说模拟出一个交换机或者集线器出来&#xff0c;把不同虚拟机连接起来&#xff0c;与物理机不进行数据交流&#xff0c;与外网也不进行数据交流&#xff0c;构建一个独立的网络。没有DHCP功能&#xff0c;需要手工配置IP或者单独配置DHCP服务器。

AG-Grid JavaScript 29.3.5 企业版 注册版

世界上最好的 JavaScript 网格 开发人员构建企业应用程序的专业选择 开始吧 Javascript 数据网格 Javascript 反应数据网格 反应 角度数据网格 有角的 Vue 数据网格 视图 实体数据网格 坚硬的 有很多基于组件的表库&#xff0c;但我相信 AG Grid 是黄金标准&#xff0c;也是我最…

抖音账号矩阵系统开发源码

技术自研框架开发背景&#xff1a; 抖音账号矩阵系统是一种基于数据分析和管理的全新平台&#xff0c;能够帮助用户更好地管理、扩展和营销抖音账号。 部分源码分享&#xff1a; //计算分页$active_list_all $Video_model->getCount($where);$page_libs new Libs_Pagin…

Mysql5.7.x镜像开启log-bin失效及解决

文章目录 [toc] 1.问题2.mysql5.7.16的部署及开启log-bin2.1 准备挂载目录2.2 启动容器命令2.3 开启log-bin配置文件内容 3.原因及解决办法4.了解binlog和redolog有什么区别&#xff1f;5.总结 1.问题 由于在本地搭建了一个数据同步的环境用到了mysql&#xff0c;所以用Docker的…

肠道健康从核心菌属开始:肠道菌群的关键

谷禾健康 5月29日&#xff0c;是世界肠道健康日。肠道是人体最重要的消化系统之一&#xff0c;与人体健康紧密相关。而肠道菌群作为肠道重要组成部分&#xff0c;在肠道健康中发挥着重要的作用。 编辑​ 由于基因、环境、饮食、药物等因素的影响&#xff0c;每个人的肠道菌群都…

前端VUE3+Vite +UniAPP-- 框架搭建

除了HBuilderX可视化界面&#xff0c;也可以使用 cli 脚手架&#xff0c;可以通过 vue-cli 创建 uni-app 项目。 全局安装 vue-cli 官网 npm install -g vue/cli npx degit dcloudio/uni-preset-vue#vite-ts vue3-uniapp配置tailwindcss插件 官网 npm install tailwindcss np…

揭秘阿里云Flink智能诊断利器——Fllink Job Advisor

引言 阿里云实时计算Flink作为一款专业级别的高性能实时大数据处理系统&#xff0c;它在各种业务场景中都发挥了关键的作用。丰富而复杂的上下游系统让它能够支撑实时数仓、实时风控、实时机器学习等多样化的应用场景。然而&#xff0c;随着系统的复杂性增加&#xff0c;用户在…

判断数的奇偶性

1 问题 如何用一个简单的程序判断一个数的奇偶性。 2 方法 import java.util.Scanner; public class HOMEWORK{ public static void main(String[] args){ System.out.println("请输入一个数"); int input new Scanner(System.in).nextInt(); if(input % 2 0){ Sys…

wsl下安装centenos7以及遇到问题报错解决

安装 ①CentenOs7-WSL 下载地址 https://github.com/yuk7/CentWSL ②解压下载的CentenOs7到自己想要安装的位置&#xff0c;解压的目录就是CentenOs的安装目录。刚开始是没有ext4.vhdx的&#xff0c;安装完成就出现了 ③安装完成&#xff0c;再次运行CentenOs.exe就可以使用了…

软件测试工程师如何从功能测试转成自动化测试

功能测试转成自动化测试&#xff0c;答案就三个字&#xff1a;“靠学习”。 学习自动化的方法无非是三种&#xff1a; 一、靠培训&#xff08;下方有如何选择培训机构&#xff09; 在相对有氛围的学习环境中来学习自动化测试&#xff0c;这是一个较快学习的方法。二、靠自学自…

切片辅助超推理(SAHI )技术原理介绍

小物体检测是指识别和定位数字图像中尺寸相对较小的物体的任务。这些对象通常具有有限的空间范围和低像素覆盖率,并且由于它们的小外观和低信噪比可能难以检测。 小物体检测的应用 小物体检测有多种应用: 监视和安全:识别和跟踪拥挤区域中的小物体,以增强公共安全。自动驾…

c盘怎么清理?这样做可以快速释放电脑空间!

案例&#xff1a;我电脑c盘可用空间已经不多了&#xff0c;出现了标红的现象&#xff0c;我想清理一下我的c盘。怎么清理c盘才科学和安全&#xff0c;才不会误删重要的文件&#xff1f;有没有小伙伴分享一下解决的方法&#xff01; C盘作为电脑系统的核心盘符&#xff0c;经常…

xxl-job Study Notes

文章目录 1 xxl-job 快速入门1.1 xxl-job是什么1.2 为什么需要xxl-job1.2.1 定时任务1.2.2 分布式任务调度1.2.3 分布式任务调度特点 1.3 xxl-job简介1.4 部署安装——基于docker1.5 xxl-job表介绍1.5 编写任务代码1.5.1 xxl-job配置1.5.2 任务代码1.5.3 分布式任务测试1.5.3.1…

计算机系统2022期末

计算机系统2022期末 本课程的复习请以知识点复习为重&#xff0c;全部内容共有大小280个知识点&#xff0c;都可能在期末考试出现&#xff0c;仅通过往年试卷复习是远远不够的&#xff0c;往年试卷仅能作为部分知识点的检测以及题目类型的大致参考&#xff0c;复习本课程需要尽…