【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
相关推荐
CoderCodingNo4 小时前
【NOIP】2011真题解析 luogu-P1003 铺地毯 | GESP三、四级以上可练习
算法
iFlyCai4 小时前
C语言中的指针
c语言·数据结构·算法
查古穆5 小时前
栈-有效的括号
java·数据结构·算法
再一次等风来5 小时前
近场声全息(NAH)仿真实现:从阵列实值信号到波数域重建
算法·matlab·信号处理·近场声全息·nah
汀、人工智能5 小时前
16 - 高级特性
数据结构·算法·数据库架构·图论·16 - 高级特性
大熊背5 小时前
利用ISP离线模式进行分块LSC校正的方法
人工智能·算法·机器学习
XWalnut5 小时前
LeetCode刷题 day4
算法·leetcode·职场和发展
蒸汽求职5 小时前
机器人软件工程(Robotics SDE):特斯拉Optimus落地引发的嵌入式C++与感知算法人才抢夺战
大数据·c++·算法·职场和发展·机器人·求职招聘·ai-native
极梦网络无忧5 小时前
OpenClaw 基础使用说明(中文版)
python
codeJinger6 小时前
【Python】操作Excel文件
python·excel