代码随想录算法训练营第24、25天|回溯理论基础、组合问题、216.组合总和III 17.电话号码的字母组合

RICHARDSON-LUCY 去卷积简介 Lucy去卷积1.泊松过程及联合概率分布2.极大似然估计参考文献 1.泊松过程及联合概率分布 首先假设相机接收光子生成图像的过程符合泊松分布。 因此,一次曝光过程中,某像素位置接收到iii个光子的概率p(i)p(i)p(i)为: p(i)=exp⁡(−λ)⋅λii!\qquad\qquad p(i)=\exp(-\lambda)\cdot\cfrac{\lambda^{i}}{i!}p(i)=exp(−λ)⋅i!λi​ 那么针对一张M∗NM*NM∗N的图像,所有像素的联合概率分布可以描述为: P(I)=∏e 阅读详情


前言

回溯理论基础

回溯可以用于解决一些经典的问题,可以看到理论框架,
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
回溯的框架
在这里插入图片描述

77、组合问题

在这里插入图片描述

思路

回溯算法引入:C5-2这样的组合问题可以用两层for循环来实现,C5-3就是再套一层for循环,如果是C100-50呢?50层for循环。所以需要使用回溯算法;

  • 核心在于:递归几次就是for循环几次
  • 回溯算法就是使得这样的递归可以得到想要的结果:💖💜即,for给每一个元素遍历的时候,每一个元素都是需要递归的,所以进入了第一个元素之后出来需要回溯,pop掉第一个元素,然后再进入第二个元素; 所以回溯是紧跟在递归的后面,也是只在单层逻辑里面

按照老师的解题思路
首先看一下构建的树形结构
在这里插入图片描述
每次从集合中选取元素,可选择的范围随着选择的进行而收缩,调整可选择的范围。
图中可以发现n相当于树的宽度,k相当于树的深度。

那么如何在这个树上遍历,然后收集到我们要的结果集呢?

图中每次搜索到了叶子节点,我们就找到了一个结果。

相当于只需要把达到叶子节点的结果收集起来,就可以求得 n个数中k个数的组合集合。
???有毒吧突然卡了写不了
回溯三部曲【看教程】
传入传出:定义两个全局变量,一个用来存放符合条件单一结果,一个用来存放符合条件结果的集合。传入startIndex来记录下一层递归,搜索的起始位置。

终止条件:path记录的长度等于k了

其中单层逻辑:
for循环每次从startIndex开始遍历,然后用path保存取到的节点i。
在这里插入图片描述

方法一 没有剪枝

下面是我自己写的代码
💦💘同样的错误:结果传入的时候必须是浅复制之后的self.result.append(self.path[:]),而不是self.result.append(self.path),因为python是指向变量空间,self.path最后为空,这会导致结果为空

class Solution(object):
    def __init__(self):
        self.path = []
        self.result = []
    def backtrack(self,n,k,startindex):
        #终止条件
        if len(self.path) == k:
            self.result.append(self.path[:])#必须要是复制切片
            return
        #单层递归逻辑,也就是处理一个节点
        for i  in range(startindex,n+1):
            print(i)
            self.path.append(i)
            print(self.path)
            self.backtrack(n,k,i+1)
            self.path.pop()
        return 
            

    def combine(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: List[List[int]]
        """
        self.backtrack(n,k,1)
        return self.result

方法二 剪枝

老师讲解了一个非常常见的剪枝思路:单层逻辑中修改for遍历的范围在这里插入图片描述
具体思路:如果for循环选择的起始位置之后的元素个数 已经不足 我们需要的元素个数了,那么就没有必要搜索了。
具体实现:
在这里插入图片描述
注意:range是不包括右边界的,所以需要再+1

class Solution(object):
    def __init__(self):
        self.path = []
        self.result = []
    def backtrack(self,n,k,startindex):
        #终止条件
        if len(self.path) == k:
            self.result.append(self.path[:])#必须要是复制切片
            return
        #单层递归逻辑,也就是处理一个节点
        for i  in range(startindex,n-(k-len(self.path))+2):
            print(i)
            self.path.append(i)
            print(self.path)
            self.backtrack(n,k,i+1)
            self.path.pop()
        return 
            

    def combine(self, n, k):
        """
        :type n: int
        :type k: int
        :rtype: List[List[int]]
        """
        self.backtrack(n,k,1)
        return self.result

216.组合总和III

在这里插入图片描述

思路

方法一 没有剪枝

这是没听讲解直接写的,确实有了前面的基础就很简答了。

class Solution(object):
    def __init__(self):
        self.result = []
        self.path = []
        self.count = 0
    def backtrace(self,target,k,startindex):
        if len(self.path) == k:
            if self.count == target:
                self.result.append(self.path[:])
            return
        for i in range(startindex,10):
            self.path.append(i)
            self.count += i
            self.backtrace(target,k,i+1)
            self.count -= i
            self.path.pop()
    def combinationSum3(self, k, n):
        """
        :type k: int
        :type n: int
        :rtype: List[List[int]]
        """
        self.backtrace(n,k,1)
        return self.result

方法二 有剪枝

当然,剪枝的思路有两个

  1. size角度:和之前一样,就是改变for循环语句
    for i in range(startindex,10-(k-len(self.path))+1):
  2. count的角度,如果当前的sum已经大于目标sum了,就返回。
class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        result = []  # 存放结果集
        self.backtracking(n, k, 0, 1, [], result)
        return result

    def backtracking(self, targetSum, k, currentSum, startIndex, path, result):
        if currentSum > targetSum:  # 剪枝操作
            return  # 如果path的长度等于k但currentSum不等于targetSum,则直接返回
        if len(path) == k:
            if currentSum == targetSum:
                result.append(path[:])
            return
        for i in range(startIndex, 9 - (k - len(path)) + 2):  # 剪枝
            currentSum += i  # 处理
            path.append(i)  # 处理
            self.backtracking(targetSum, k, currentSum, i + 1, path, result)  # 注意i+1调整startIndex
            currentSum -= i  # 回溯
            path.pop()  # 回溯

17.电话号码的字母组合

在这里插入图片描述

思路

本题思路依然和之前的差不多;不多要注意细节的传入参数,我自己就没有想出来
回溯三部曲

  1. 传入传出参数:传入的应该是digits和指向digits的index(表示是digits中第几个数);
  2. 终止条件:如果index大于digit-size,说明到头了
  3. 单层递归逻辑:首先要取index指向的数字,并找到对应的字符集(手机键盘的字符集)。

💛本题注意点和小细节

  • 💘使用map来表征数字和对应的字母;但是进一步可以用list来创建哈希表,其下标就是数字,元素值就是数字对应的字母(所以0和1是空的)
  • digits[index]得到的结果是“2”这样的,要记得转换为数字类型;在c++中处理的方法是int digit = digits[index] - ‘0’
  • 对于string类型的处理:python是string类型直接+就行,string类型删除的话使用[:-1]的方式;下面方法一3使用的是列表最后转为字符串,result.append(‘’.join(path))
  • 在这里插入图片描述在这里插入图片描述

方法一

下面是我自己写 的

class Solution(object):
    def __init__(self):
        self.map_ = [
            " ",#0
            " ",#1
            "abc",#2
            "def",#3
            "ghi",#4
            "jkl",#5
            "mno",#6
            "pqrs",#7
            "tuv",#8
            "wxyz",#9
        ]
        self.result = []
        self.s = ""
    def backtrace(self,digits,index_):
        if index_ == len(digits):
            self.result.append(self.s)
            return
        for i in self.map_[int(digits[index_])]:
            self.s += i
            self.backtrace(digits,index_+1)
            self.s = self.s[:-1]



    def letterCombinations(self, digits):
        """
        :type digits: str
        :rtype: List[str]
        """
        if len(digits) == 0:
            return self.result
        self.backtrace(digits,0)
        return self.result

方法一2 隐藏回溯

具体方法:self.s不再设为全局变量,而是变成参数每次传进去;
回溯的是时候变成self.backtrace(digits,index_+1,s+letter);这样s就是没有变过的;

class Solution:
    def __init__(self):
        self.letterMap = [
            "",     # 0
            "",     # 1
            "abc",  # 2
            "def",  # 3
            "ghi",  # 4
            "jkl",  # 5
            "mno",  # 6
            "pqrs", # 7
            "tuv",  # 8
            "wxyz"  # 9
        ]
        self.result = []
    
    def getCombinations(self, digits, index, s):
        if index == len(digits):
            self.result.append(s)
            return
        digit = int(digits[index])
        letters = self.letterMap[digit]
        for letter in letters:
            self.getCombinations(digits, index + 1, s + letter)
    
    def letterCombinations(self, digits):
        if len(digits) == 0:
            return self.result
        self.getCombinations(digits, 0, "")
        return self.result

方法一3 不用字符串而是列表来处理

    def getCombinations(self, digits, index, path, result):
        if index == len(digits):
            result.append(''.join(path))
            return
        digit = int(digits[index])
        letters = self.letterMap[digit]
        for letter in letters:
            path.append(letter)
            self.getCombinations(digits, index + 1, path, result)
            path.pop()
    
    def letterCombinations(self, digits):
        result = []
        if len(digits) == 0:
            return result
        self.getCombinations(digits, 0, [], result)
        return result

总结

多后端系统统一聚合与智能分流:用 Multi Origin Composition 与 Routing 打造一套可扩展的 SAP Gateway 架构 本文针对企业级SAP集成场景,详细介绍了如何利用SAP Gateway的MOC(多源组合)和Routing功能实现多后端系统的智能路由与数据聚合。通过系统别名配置、用户角色绑定和主机名分流等机制,可实现按用户、按域名的精确路由。文章还提供了配置清单、性能优化建议和常见问题解决方案,帮助工程师落地多后端OData服务的最佳实践。 阅读详情

相关推荐

【有啥问啥】智能座舱CPD技术:毫米波雷达如何守护儿童安全?

本文深入探讨了智能座舱中CPD(Child Presence Detection)技术如何通过毫米波雷达保障儿童安全。毫米波雷达凭借其穿透性检测、微动感知等优势,成为儿童遗留车内的有效解决方案。文章详细解析了技术原理、系统集成方案及安装指南,为智能座舱安全技术提供了实用参考。

weixin_29193259的博客 357

代码随想录算法训练营第22天 | 回溯算法理论基础、77. 组合、216.组合总和III、17.电话号码的字母组合

回溯法也可以叫做回溯搜索法,它是一种搜索的方式。回溯是递归的副产品,只要有递归就会有回溯。所以以下讲解中,回溯函数也就是递归函数,指的都是一个函数。

程序员黄雷的博客 2068

Python驱动COMSOL自动化:从数据生成到DNN代理模型部署全流程解析

本文详细解析了如何利用Python驱动COMSOL实现全流程自动化,从参数化建模、批量仿真数据生成,到训练深度神经网络(DNN)代理模型并部署应用。该方案通过自动化闭环解放工程师生产力,并利用代理模型实现秒级性能预测,极大提升了多物理场仿真优化与设计探索的效率。

weixin_29041767的博客 209

代码随想录算法训练营第二十二天| 回溯算法理论基础 77. 组合 216.组合总和III 17.电话号码的字母组合

回溯法章节开始,逐渐开始正式复习算法设计课的知识。文章图片来源:代码随想录 (https://programmercarl.com/)

Mwicogito的博客 3147

wifi/BT芯片RTL8723DS驱动移植和测试之一wifi篇

本文主要介绍如何在stm32mp157中移植并测试芯片RTL8723DS的wifi功能。

汉尼拔勇闯天涯 8740

Python xlwings报错解决:从‘NoneType‘到完美运行WPS表格的完整指南

本文深入解析了使用Python xlwings库自动化WPS表格时遇到的经典'NoneType'报错(AttributeError: 'NoneType' object has no attribute 'apps')的根源与解决方案。核心在于pywin32版本与WPS的兼容性问题,文章提供了从版本降级、依赖管理到构建健壮自动化环境的完整实战指南,帮助开发者彻底解决兼容性难题,实现稳定运行。

n4o5p6q7r的博客 303

代码随想录算法训练营第 22 天 |LeetCode77. 组合 LeetCode 216.组合总和III LeetCode17.电话号码的字母组合

回溯法

2301_79647020的博客 1309

遗传算法驱动吃豆人进化:从零构建AI游戏智能体

遗传算法是一种模拟自然选择过程的优化技术,其核心原理是通过选择、交叉和变异等操作,在解空间中迭代搜索最优解。该技术为解决复杂优化问题提供了强大工具,尤其在游戏AI、机器人控制和参数调优等场景中价值显著。在游戏AI领域,遗传算法常被用于训练智能体自主决策,例如在经典游戏《吃豆人》中,通过定义智能体的“基因”(如神经网络权重)和“适应度”(如游戏得分),可以引导其进化出躲避幽灵、高效吃豆等策略。本项目结合Pygame框架与神经网络,构建了一个完整的遗传算法训练沙盒,详细展示了如何通过适应度函数设计和参数调优,实

weixin_30467199的博客 273

代码随想录算法训练营Day27 | 回溯算法理论基础、77.组合、216.组合总和Ⅲ、17.电话号码的字母组合

训练营第27天:回溯算法理论基础、77.组合、216.组合总和Ⅲ、17.电话号码的字母组合

jiabao0520的博客 1230

EPO: Hierarchical LLM Agents with Environment PreferenceOptimization

长期决策和规划任务依然是基于大型语言模型(LLM)的智能体面临的一大挑战(Valmeekam 等,2023;Liu 等,2023;Silver 等,2024)。这些任务需要智能体进行多步骤的规划,同时保持行为的一致性和目标导向,这对于通常被设计用于即时和局部预测的大型语言模型来说颇为困难。此外,针对具身智能体的大型语言模型微调面临的一个关键难题是大规模标注数据的需求(Reed 等,2022)。

qq_52053775的博客 142

Cesium 实战 04 - 标绘功能系列之画点(draw point)

Cesium 实战 - 标绘功能之画点(draw point)。

非科班Java出身GISer的博客 1083

代码随想录算法训练营第十九天|理论基础、77. 组合、216.组合总和III、17.电话号码的字母组合

视频讲解:带你学透回溯算法(理论篇)| 回溯法精讲!_哔哩哔哩_bilibili关于回溯算法,我公众号里已经讲完了,并且将回溯算法专题整理成一本PDF,该PDF共5万字,包含了30多张树形结构图、15道力扣精选回溯题目,21篇回溯法精讲文章,由浅入深,绝对是全网最精良的回溯算法资料!,回溯算法套路②组合型回溯+剪枝【基础算法精讲 15】,【labuladong】回溯算法核心套路详解,十分钟快速入门贪心算法,算法20天速通!leetcodeHot100-- 回溯,启动!

qq_73932604的博客 1147

记录Android Studio连接华为(nova)手机鸿蒙系统踩过的坑

鸿蒙系统的华为老机子比较麻烦,坑有点多,兄弟们加油!

沉迷单车的追风少年 7922

代码随想录算法训练营DAY25|C++回溯算法Part.2|216. 组合总和II、17.电话号码的字母组合

状态:根据题目可知,k是决定树形结构的深度,那么要求组合为n的这个限制条件,我们如何写代码呢?树的深度是由我们输入的数字个数来定,树的宽度就是数字所对应的字母的长度来控制的。题目其实就是给定一个[1, 9]的集合,求组合,要求组合和为n,个数为k。其实也是回溯的一种体现,因为从目前的i开始,一直往后所有的i都不需要了。本题中使用二维数组来做映射,这里也回答了状态1中提出的问题。数字到字母的映射可以用map,也可以用二维数组来做映射。本质上就是在组合问题的基础上加了一个和的限制。,树的深度由k来决定。

糖炒栗子 1216

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

代码随想录算法训练营第二十二天|216.组合总和III,17.电话号码的字母组合

找出所有相加之和为 n 的 k 个数的组合,且满足下列条件:只使用数字1到9,每个数字 最多使用一次 返回 所有可能的有效组合的列表。该列表不能包含相同的组合两次,组合可以以任何顺序返回。给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。给出数字到字母的映射与电话按键相同。注意 1 不对应任何字母。

weixin_47748259的博客 1323

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

代码随想录算法训练营第二十二天 | 回溯算法理论基础、77. 组合、216.组合总和III、17.电话号码的字母组合

代码随想录算法训练营第二十二天 | 回溯算法理论基础、77. 组合、216.组合总和III、17.电话号码的字母组合

2301_81109252的博客 1097

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

代码随想录算法训练营第25天 | 216.组合总和III 17.电话号码的字母组合

图中可以看出遍历的深度,就是输入"23"的长度,而叶子节点就是我们要收集的结果,输出["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]。其实这里sum这个参数也可以省略,每次targetSum减去选取的元素数值,然后判断如果targetSum为0了,说明收集到符合条件的结果了,我这里为了直观便于理解,还是加一个sum参数。如果此时path里收集到的元素和(sum) 和targetSum(就是题目描述的n)相同了,就用result收集当前的结果。

Laulian的博客 1003

代码随想录算法训练营第十九天 | LeetCode77.组合、LeetCode216.组合总和III、LeetCode17.电话号码的字母组合

很暴力的方法我知道,无非就是字符串中每一个字符对应一个集合,然后集合里的元素互相匹配,但是不知道怎么用代码实现。:和前面组合问题不能,树中每层节点为新的集合,所以index应该指向新的字母进行递归。:思路一致,但剪枝更加彻底,一方面是超过了目标和,另一方面是剩余元素个数小于k。回溯法解决的问题:组合问题、切割问题、子集问题、排列问题、棋盘问题。:照猫画虎,组合问题每次就取当前元素后面的范围中k-1的数的组合。该列表不能包含相同的组合两次,组合可以以任何顺序返回。的字符串,返回所有它能表示的字母组合。

zhuabazhuabahuo的博客 1058

代码随想录算法训练营Day19| LeetCode 77 组合、216 组合总和 III、17 电话号码的字母组合

代码随想录算法训练营第十九天!开启回溯算法章节!

修炼途中的所见所闻,所思所想。 1112

代码随想录算法训练营第22天 | 题目:回溯算法part01 理论基础、77. 组合 、 216.组合总和III 、 17.电话号码的字母组合

从下图中红线部分可以看出,在集合[1,2,3,4]取1之后,下一层递归,就要在[2,3,4]中取数了,那么下一层递归如何知道从[2,3,4]中取数呢,靠的就是startIndex。第一次取1,集合变为2,3,4 ,因为k为2,我们只需要再取一个数就可以了,分别取2,3,4,得到集合[1,2] [1,3] [1,4],以此类推。示例: 输入: n = 4, k = 2 输出: [ [2,4], [3,4], [2,3], [1,2], [1,3], [1,4], ],9],所以for循环固定i<=9。

weixin_51303606的博客 890

代码随想录算法训练营第二十天 |【回溯】77. 组合、 216.组合总和III、17.电话号码的字母组合

回溯法也可以叫做回溯搜索法,它是一种搜索的方式。回溯是递归的副产品,只要有递归就会有回溯。所以以下讲解中,回溯函数也就是递归函数,指的都是一个函数。本篇我们准对求组合问题的回溯法代码做了剪枝优化,这个优化如果不画图的话,其实不好理解,也不好讲清楚。所以我依然是把整个回溯过程抽象为一棵树形结构,然后可以直观的看出,剪枝究竟是剪的哪里。力扣题目链接(opens new window)您需要在二叉树的每一行中找到最大的值。

qq_43714515的博客 928

代码随想录算法训练营第二十五天 | 216.组合总和III,17.电话号码的字母组合 [回溯篇]

回溯、数字组合、电话号码的字母组合

leehal的博客 953

代码随想录算法训练营第二十五天| 216. 组合总和 III、17. 电话号码的字母组合

题目:找出所有相加之和为n的k返回所有可能的有效组合的列表。该列表不能包含相同的组合两次,组合可以以任何顺序返回。= 3,= 7[[1,2,4]]没有其他符合的组合了。= 3,= 9没有其他符合的组合了。[]不存在有效的组合。在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。

924

代码随想录算法训练营第二十二天|LeetCode 回溯算法理论基础、77. 组合、216.组合总和III、17.电话号码的字母组合

一篇文章搞懂回溯算法!回溯算法答题模板!组合问题经典例题!

Anastasia_sakura的博客 1082

代码随想录算法训练营Day22|回溯算法Part01| 77. 组合、216.组合总和III、17.电话号码的字母组合

本文总结了三个回溯算法典型问题:组合问题(77)、组合总和III(216)和电话号码字母组合(17)。针对77题,重点讲解了回溯模板和避免结果被清空的技巧;216题在组合基础上增加了求和条件;17题则展示了字符串处理中的回溯应用。文章提供了各题的完整代码实现,并强调了关键注意事项:如结果存储需复制列表而非引用,以及StringBuilder的操作方法。这些题目共享回溯算法的核心思想,通过递归和剪枝解决问题,是理解回溯算法的经典范例。

m0_71282417的博客 740

代码随想录算法训练营第二十五天|Leetcode216 组合总和III、Leetcode17 电话号码的字母组合

对于电话号码的字母组合,就是依次地从每一个字符串中取一个字符进行配对,也能转换为相对应的树形结构,递归深度取决于输入数字的个数,宽度取决于第一个字符串的大小。在[1,9]范围内使用4个不同的数字,我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。我们需要将字符串与输入的数字字符串进行一个映射,因为是对全局变量进行修改,因此该函数不需要任何返回值,参数需要传入。因为递归和回溯必须相匹配,所以我们在递归结束之后,从s中弹出当前遍历字符,然后进行之后的递归操作。

Demok123的博客 997
上一篇: 代码随想录算法训练营 day23| ● 669. 修剪二叉搜索树 ● 108.将有序数组转换为二叉搜索树 ● 538.把二叉搜索树转换为累加树
下一篇: day27-29| 39组合总和40 数组总和II13分割回文串93.复原IP地址78子集90子集II491递增子序列46全排列47全排列II332重新安排行程37解数独
Xalileetcode
博客等级 码龄7年 482粉丝 43原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值