六六力扣刷题回溯之组合总和

简介: 之前小六六一直觉得自己的算法比较菜,算是一个短板吧,以前刷题也还真是三天打鱼,两台晒网,刷几天,然后就慢慢的不坚持了,所以这次,借助平台的活动,打算慢慢的开始开刷,并且自己还会给刷的题总结下,谈谈自己的一些思考,和自己的思路等等,希望对小伙伴能有所帮助吧,也可以借此机会把自己短板补一补,希望自己能坚持下去呀

题目


组合总和 III 216题

找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:

只使用数字1到9 每个数字 最多使用一次  返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。

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


分析


其实大家可以看看这题,也是用回溯算法解决的,最近几天,六六分享的都是回溯算法的,关于回溯算法的定义啥的,可以看上面那篇文章,这边我们就直接把模版拿出来,大家就像填词一样,往里面填代码试试,


模版


回溯三部曲

  • 1.确定回溯单层逻辑

通过for循环控制当前位置(也就是当前递归层)的数字可以从1选到9,每选择一个数字(for每遍历到一个数字)我们就从目标总和中减去它的值,同时把他加入记录数字组合的集合中; 通过上一步我们就确定了第一位数字,接下来通过递归确定下一位数字,要注意的是需要更新下一层递归选择下一位数字时开始的位置,因为上一层选过的数字下一层就不能再选了; 当递归到某层时,我们发现此时已经确定了k个数字了,需要判断这k个数的和是否等于n,如果等于n,则把这次收集到的组合加入最终的结果集并终止当前层递归,准备回溯;反之,直接终止递归,准备回溯; 当我们从上一层递归中出来后,就该回溯了,即删掉最后一位的数字重新选择一个新数字;

  • 2.确定回溯函数参数以及返回值

根据上述分析,可以得知我们在每层的递归中都会更新目标总和的值、判断当前是否选够了k个数字、以及我们必须直到当前这层递归中选择数字的起点在哪里 因此参数需要:目标总和、题目给出的k、当前层递归选择数字的起始位置 因为我们将用两个全局变量记录当前组合以及最终结果集,所以不需要返回值

  • 3.确定回溯函数终止条件

在分析单层逻辑时,我们就已经得到:当我们选取了k个数字后们就一个终止当前递归返回了

void backtracking(参数) {
    if (终止条件) {
        存放结果;
        return;
    }
    for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
        处理节点;
        backtracking(路径,选择列表); // 递归
        回溯,撤销处理结果
    }
}
复制代码


题解


package com.six.finger.leetcode.five;
/*
找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:
只使用数字1到9
每个数字 最多使用一次 
返回 所有可能的有效组合的列表 。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
输入: k = 3, n = 7
输出: [[1,2,4]]
解释:
1 + 2 + 4 = 7
没有其他符合的组合了。
 */
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class fifteen {
    public static void main(String[] args) {
        combinationsum(9, 45);
    }
    public static List<List<Integer>> combinationsum(int k, int n) {
        List<List<Integer>> res = new ArrayList<>();
        LinkedList<Integer> path = new LinkedList<>();
        backtracking(res, path, k, n, 1);
        return res;
    }
    private static void backtracking(List<List<Integer>> res, LinkedList<Integer> path, int k, int n, int i) {
        int sum = 0;
        //第一步,递归的退出条件
        for (Integer integer : path) {
            sum = sum + integer;
        }
        if (sum > n) {
            return;
        }
        if (sum == n && path.size() == k) {
            res.add(new ArrayList<>(path));
            return;
        }
        //第二步 树的横向长度,和减枝活动
        for (int j = i; j <= 9 - (k - path.size()) + 1; j++) {
            path.add(j);
            backtracking(res, path, k, n, j + 1);
            path.removeLast();
        }
    }
}
复制代码


网络异常,图片无法展示
|


网络异常,图片无法展示
|

一看提交记录,我去太菜了,想想怎么优化下


优化


其实就是,我为啥每次都要计算path的和,改下,把这样计算

for (int j = i; j <= 9 - (k - path.size()) + 1; j++) {
    sum=sum+i;
    path.add(j);
    backtracking(res, path, k, n, j + 1,sum);
    path.removeLast();
    sum=sum-i;
}
复制代码


网络异常,图片无法展示
|


然后并没有什么用哦

结束


好了,今天这题就结束了,我发现连续的去练一种类型,其实这种题就慢慢的没那么难了,以前我总觉得算法很难,但是其实万事万物,都有其自然的规律,我们只能善于总结,虽然创造不出什么新的东西,但是还是可以把别人的经验学习到的,加油!!

相关文章
|
4月前
|
Unix Shell Linux
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
本文提供了几个Linux shell脚本编程问题的解决方案,包括转置文件内容、统计词频、验证有效电话号码和提取文件的第十行,每个问题都给出了至少一种实现方法。
LeetCode刷题 Shell编程四则 | 194. 转置文件 192. 统计词频 193. 有效电话号码 195. 第十行
|
5月前
|
Python
【Leetcode刷题Python】剑指 Offer 32 - III. 从上到下打印二叉树 III
本文介绍了两种Python实现方法,用于按照之字形顺序打印二叉树的层次遍历结果,实现了在奇数层正序、偶数层反序打印节点的功能。
68 6
|
5月前
|
Python
【Leetcode刷题Python】剑指 Offer 26. 树的子结构
这篇文章提供了解决LeetCode上"剑指Offer 26. 树的子结构"问题的Python代码实现和解析,判断一棵树B是否是另一棵树A的子结构。
65 4
|
5月前
|
搜索推荐 索引 Python
【Leetcode刷题Python】牛客. 数组中未出现的最小正整数
本文介绍了牛客网题目"数组中未出现的最小正整数"的解法,提供了一种满足O(n)时间复杂度和O(1)空间复杂度要求的原地排序算法,并给出了Python实现代码。
137 2
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
280页PDF,全方位评估OpenAI o1,Leetcode刷题准确率竟这么高
【10月更文挑战第24天】近年来,OpenAI的o1模型在大型语言模型(LLMs)中脱颖而出,展现出卓越的推理能力和知识整合能力。基于Transformer架构,o1模型采用了链式思维和强化学习等先进技术,显著提升了其在编程竞赛、医学影像报告生成、数学问题解决、自然语言推理和芯片设计等领域的表现。本文将全面评估o1模型的性能及其对AI研究和应用的潜在影响。
72 1
|
4月前
|
数据采集 负载均衡 安全
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
本文提供了多个多线程编程问题的解决方案,包括设计有限阻塞队列、多线程网页爬虫、红绿灯路口等,每个问题都给出了至少一种实现方法,涵盖了互斥锁、条件变量、信号量等线程同步机制的使用。
LeetCode刷题 多线程编程九则 | 1188. 设计有限阻塞队列 1242. 多线程网页爬虫 1279. 红绿灯路口
|
5月前
|
索引 Python
【Leetcode刷题Python】从列表list中创建一颗二叉树
本文介绍了如何使用Python递归函数从列表中创建二叉树,其中每个节点的左右子节点索引分别是当前节点索引的2倍加1和2倍加2。
83 7
|
5月前
|
Python
【Leetcode刷题Python】剑指 Offer 22. 链表中倒数第k个节点
Leetcode题目"剑指 Offer 22. 链表中倒数第k个节点"的Python解决方案,使用双指针法找到并返回链表中倒数第k个节点。
62 5
|
5月前
|
Python
【Leetcode刷题Python】剑指 Offer 30. 包含min函数的栈
本文提供了实现一个包含min函数的栈的Python代码,确保min、push和pop操作的时间复杂度为O(1)。
39 4
|
5月前
|
Python
【Leetcode刷题Python】剑指 Offer 21. 调整数组顺序使奇数位于偶数前面
Leetcode题目"剑指 Offer 21. 调整数组顺序使奇数位于偶数前面"的两种Python解决方案,一种是使用双端队列调整数组顺序,另一种是使用双指针法将奇数移到数组前半部分,偶数移到后半部分。
33 4