当前位置: 首页 > ds >正文

代码随想录Day20

代码随想录Day20

第一题:39. 组合总和

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

  • 题目思路:这道题目和之前做的组合问题差不多,区别就是在于这道题目选取的组合是可以重复的也就说明我们在递归的时候不需要从 i+1开始而是直接从i开始即可
  • AC代码
class Solution {List<List<Integer>> result = new ArrayList<>();List<Integer> path = new LinkedList<>();public List<List<Integer>> combinationSum(int[] candidates, int target) {Arrays.sort(candidates);backTracking(candidates, target, 0, 0);return result;}private void backTracking(int[] candidates, int target, int sum, int startIndex) {//确定回溯的终止条件if (sum > target) return;if (sum == target) {result.add(new ArrayList<>(path));return;}//确定单层搜索的条件for (int i = startIndex; i < candidates.length && sum + candidates[i] <= target; i++) {sum += candidates[i];path.add(candidates[i]);backTracking(candidates, target, sum, i);//传入 i 表示可以选取重复的元素sum -= candidates[i];path.removeLast();}}
}

第二题:40. 组合总和 II

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次

**注意:**解集不能包含重复的组合。

  • 题目思路:

    • 这道题目和上一道题目比起来难度就大了一些首先我们需要理解的是这道题目中说的不能重复是什么意思,这里的不能重复是指单个集合也就是树枝中可以有重复的元素但是同一层内不能有重复的集合

    • 因此这道题的关键就是去重,对于去重我们这里引入一个used数组来进行去重

    • 单层搜索的逻辑:

      这里与39.组合总和 (opens new window)最大的不同就是要去重了。

      前面我们提到:要去重的是“同一树层上的使用过”,如何判断同一树层上元素(相同的元素)是否使用过了呢。

      如果candidates[i] == candidates[i - 1] 并且 used[i - 1] == false,就说明:前一个树枝,使用了candidates[i - 1],也就是说同一树层使用过candidates[i - 1]

      此时for循环里就应该做continue的操作。

      • used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
      • used[i - 1] == false,说明同一树层candidates[i - 1]使用过

      可能有的录友想,为什么 used[i - 1] == false 就是同一树层呢,因为同一树层,used[i - 1] == false 才能表示,当前取的 candidates[i] 是从 candidates[i - 1] 回溯而来的。

      而 used[i - 1] == true,说明是进入下一层递归,去下一个数,所以是树枝上

  • AC代码

class Solution {List<List<Integer>> result = new ArrayList<>();List<Integer> path = new LinkedList<>();public List<List<Integer>> combinationSum2(int[] candidates, int target) {Arrays.sort(candidates);boolean[] used = new boolean[candidates.length];//将used数组初始值全部设为falseArrays.fill(used, false);backTracking(candidates, target, 0, 0, used);return result;}private void backTracking(int[] candidates, int target, int sum, int startIndex, boolean[] used) {if (sum == target) {result.add(new ArrayList<>(path));return;}//确定单层搜索的逻辑for (int i = startIndex; i < candidates.length && sum + candidates[i] <= target; i++) {// 要对同一树层使用过的元素进行跳过if (i > 0 && candidates[i] == candidates[i - 1] && used[i - 1] == false) {continue;}sum += candidates[i];path.add(candidates[i]);used[i] = true;backTracking(candidates, target, sum, i + 1, used);used[i] = false;sum -= candidates[i];path.removeLast();}}
}

第三题:131. 分割回文串

给你一个字符串 s,请你将 s 分割成一些 子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。

  • 题目思路:

    • 这种题目,想用for循环暴力解法,可能都不那么容易写出来,所以要换一种暴力的方式,就是回溯。

    一些同学可能想不清楚 回溯究竟是如何切割字符串呢?

    我们来分析一下切割,其实切割问题类似组合问题

    例如对于字符串abcdef:

    • 组合问题:选取一个a之后,在bcdef中再去选取第二个,选取b之后在cdef中再选取第三个…。

    • 切割问题:切割一个a之后,在bcdef中再去切割第二段,切割b之后在cdef中再切割第三段…。

    • 递归用来纵向遍历,for循环用来横向遍历,切割线(就是图中的红线)切割到字符串的结尾位置,说明找到了一个切割方法。

      此时可以发现,切割问题的回溯搜索的过程和组合问题的回溯搜索的过程是差不多的。

  • AC代码

class Solution {List<List<String>> result = new ArrayList<>();List<String> path = new LinkedList<>();public List<List<String>> partition(String s) {backTracking(s, 0);return result;}private void backTracking(String s, int startIndex) {if (startIndex >= s.length()) {result.add(new ArrayList<>(path));return;}//确定单层搜索逻辑for (int i = startIndex; i < s.length(); i++) {if (isPalindrome(s, startIndex, i)) {String str = s.substring(startIndex, i + 1);path.add(str);} else continue;backTracking(s, i + 1);path.removeLast();}}/*** 判断是否是回文字串** @param s* @param start* @param end* @return*/private boolean isPalindrome(String s, int start, int end) {for (int i = start, j = end; i < j; i++, j--) {if (s.charAt(i) != s.charAt(j)) {return false;}}return true;}
}
http://www.xdnf.cn/news/4609.html

相关文章:

  • Canal mysql to mysql 增加 online 库同步配置指南
  • MATLAB技巧——命令行输入的绘图,中文是正常的,到了脚本(m文件)里面就变成乱码的解决方法
  • 普通笔记本与军用加固笔记本电脑的区别,探索防水、防爆、防摔的真·移动工作站!
  • 2025软考【系统架构设计师】:两周极限冲刺攻略(附知识点解析+答题技巧)
  • java ReentrantLock
  • MySQL的基本操作
  • 《Python星球日记》 第46天:决策树与随机森林
  • 二分查找习题
  • SQL 中的中括号 [ ]、双引号 “ “、反引号 ` `:SQL Server、Oracle、MySQL三大数据库标识符 定界符 详解
  • Xilinx XCKU11P-2FFVA1156I 赛灵思 FPGA AMD Kintex UltraScale+
  • K8S - 金丝雀发布实战 - Argo Rollouts 流量控制解析
  • Python案例实战《鲜花识别模型训练及调用》
  • 使用 Selenium 截图功能,截不到原生 JavaScript 弹窗
  • 【视觉基础模型-SAM系列-2】SAM2: Segment Anything in Images and Videos
  • 【上位机——MFC】对象和控件绑定
  • kettle从入门到精通 第九十六课 ETL之kettle Elasticsearch 增删改查彻底掌握
  • C++GO语言socket套接字
  • Go语言——for循环、包构建以及包冲突
  • 怎样避免住宅IP被平台识别
  • Prompt Engineering 提示词工程学习
  • 【iscsi】服务器重启找不到iscsi的磁盘,导致磁盘挂载失败
  • uniapp 震动功能实现
  • 约瑟夫josephu问题
  • 企业数字化转型第二课:接受不完美(1/2)
  • MCP相关标的梳理
  • ​​大疆无人机“指点飞行模式”​​(TapFly)
  • 居民健康监测小程序|基于微信小程序的居民健康监测小程序设计与实现(源码+数据库+文档)
  • RT Thread Studio创建软件和硬件RTC工程
  • WebGIS开发面试题:前端篇(三)
  • 深入理解Java反射机制