【Day20】LeetCode:39. 组合总和,40. 组合总和II,131. 分割回文串

文章目录

  • [LeetCode:39. 组合总和](#LeetCode:39. 组合总和)
  • [LeetCode:40. 组合总和II](#LeetCode:40. 组合总和II)
  • [LeetCode:131. 分割回文串](#LeetCode:131. 分割回文串)

LeetCode:39. 组合总和

https://leetcode.cn/problems/combination-sum/description/

思路

先将 candidates 排序。排序后,如果当前数字已经大于剩余目标值,那么它后面的数字只会更大,可以立即跳出循环。

解答

python 复制代码
class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        def backtrack(remaining, start, current):
            if remaining == 0: # 如果剩余值为0,说明当前组合有效
                result.append(list(current))
                return

            for i in range(start, len(candidates)):
                num = candidates[i]
                if num > remaining:
                    break

                current.append(num)
                backtrack(remaining - num, i, current)
                current.pop()

        candidates.sort() # 排序以便剪枝
        result = []
        backtrack(target, 0, [])
        return result

LeetCode:40. 组合总和II

https://leetcode.cn/problems/combination-sum-ii/

思路

先将 candidates 排序。同一层递归中,如果当前数字和前一个数字相同,并且前一个数字在本层已经使用过(即 i > start),那么以当前数字开头的所有组合都会与以前一个数字开头的组合重复,因此跳过。注意这里 i > start 的条件保证了我们只跳过同一层中的重复,而不影响不同层(例如 1,1,2 中两个 1 可以同时出现在一个组合中,因为它们在递归的不同层)。

解答

python 复制代码
class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        results = []
        n = len(candidates)

        def backtrack(remain: int, start: int, path: List[int]) -> None:
            if remain == 0:
                results.append(path[:])
                return

            for i in range(start, n):
                if candidates[i] > remain:
                    break

                # 去重:同一层递归中,如果当前数字和前一个数字相同,跳过
                if i > start and candidates[i] == candidates[i - 1]:
                    continue

                path.append(candidates[i])
                backtrack(remain - candidates[i], i + 1, path)
                path.pop()

        candidates.sort()
        backtrack(target, 0, [])
        return results

LeetCode:131. 分割回文串

https://leetcode.cn/problems/palindrome-partitioning/description/

思路

  1. 从字符串的起始位置 start 开始遍历,尝试所有可能的分割点 end

  2. 对于每个分割点,检查子串 s[start:end+1] 是否是回文。

    (1)如果是,则将该子串加入当前路径 path,然后递归处理剩余部分。

    (2)如果不是,则跳过该分割点,继续尝试下一个。

  3. start 到达字符串末尾时,说明找到了一个完整的分割方案,将当前路径加入结果。

  4. 回溯:在递归返回后,将最后加入的子串弹出,以便尝试其他分割方式。

解答

python 复制代码
class Solution:
    def partition(self, s: str) -> List[List[str]]:
        n = len(s)

        results = []
        path = []

        def backtrack(start: int):
            if start == n:
                results.append(path[:])
                return
                
            for end in range(start, n): # 枚举子串的结束位置
                sub_s = s[start:end+1]
                if sub_s == sub_s[::-1]: # 子串 s[start:end+1] 是回文
                    path.append(sub_s)
                    backtrack(end + 1)
                    path.pop()

        backtrack(0)
        return results
相关推荐
我的xiaodoujiao2 小时前
快速学习Python基础知识详细图文教程9--函数进阶
开发语言·python·学习·测试工具
战族狼魂2 小时前
高频面试题精选:分治与AI Agent架构
人工智能·算法·大模型·大语言模型
weixin_408099672 小时前
2026 图片去水印 API 接口完全指南:一键去除图片水印(附 Python/Java/PHP/C# 示例)
java·python·php·图片处理·api调用·图片去水印·石榴智能
李剑一2 小时前
你用过网易的将军令嘛?它底层实现账号保护的原理相当简单粗暴
算法
Scott9999HH2 小时前
告别流量波动玄学!从法拉第电磁定律到底层 C/C++ 流量累积算法,深度解密工业级电磁流量计选型与开发
c语言·c++·算法
去码头整点薯条ing3 小时前
某当网登录滑块【协议+OCR】
爬虫·python·ocr
香辣牛肉饭3 小时前
【算法】动态规划 最长公共子序列(LCS)
经验分享·笔记·算法·动态规划
赶紧写完去睡觉3 小时前
Anaconda 创建虚拟环境与使用
python·pycharm·conda
迷途呀3 小时前
Python:函数中的参数类型
开发语言·笔记·python·langchain·nlp