代码随想录-算法训练营day27【回溯03:组合总和、分割回文串】

本文主要是介绍代码随想录-算法训练营day27【回溯03:组合总和、分割回文串】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

代码随想录-035期-算法训练营【博客笔记汇总表】-CSDN博客

第七章 回溯算法part03● 39. 组合总和
● 40.组合总和II
● 131.分割回文串详细布置 39. 组合总和 本题是 集合里元素可以用无数次,那么和组合问题的差别 其实仅在于 startIndex上的控制题目链接/文章讲解:https://programmercarl.com/0039.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8C.html 
视频讲解:https://www.bilibili.com/video/BV1KT4y1M7HJ  40.组合总和II 本题开始涉及到一个问题了:去重。注意题目中给我们 集合是有重复元素的,那么求出来的 组合有可能重复,但题目要求不能有重复组合。 题目链接/文章讲解:https://programmercarl.com/0040.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8CII.html   
视频讲解:https://www.bilibili.com/video/BV12V4y1V73A131.分割回文串  本题较难,大家先看视频来理解 分割问题,明天还会有一道分割问题,先打打基础。 https://programmercarl.com/0131.%E5%88%86%E5%89%B2%E5%9B%9E%E6%96%87%E4%B8%B2.html  
视频讲解:https://www.bilibili.com/video/BV1c54y1e7k6  往日任务
● day 1 任务以及具体安排:https://docs.qq.com/doc/DUG9UR2ZUc3BjRUdY  
● day 2 任务以及具体安排:https://docs.qq.com/doc/DUGRwWXNOVEpyaVpG  
● day 3 任务以及具体安排:https://docs.qq.com/doc/DUGdqYWNYeGhlaVR6 
● day 4 任务以及具体安排:https://docs.qq.com/doc/DUFNjYUxYRHRVWklp 
● day 5 周日休息
● day 6 任务以及具体安排:https://docs.qq.com/doc/DUEtFSGdreWRuR2p4 
● day 7 任务以及具体安排:https://docs.qq.com/doc/DUElCb1NyTVpXa0Jj 
● day 8 任务以及具体安排:https://docs.qq.com/doc/DUGdsY2JFaFhDRVZH 
● day 9 任务以及具体安排:https://docs.qq.com/doc/DUHVXSnZNaXpVUHN4 
● day 10 任务以及具体安排:https://docs.qq.com/doc/DUElqeHh3cndDbW1Q 
●day 11 任务以及具体安排:https://docs.qq.com/doc/DUHh6UE5hUUZOZUd0 
●day 12 周日休息 
●day 13 任务以及具体安排:https://docs.qq.com/doc/DUHNpa3F4b2dMUWJ3 
●day 14 任务以及具体安排:https://docs.qq.com/doc/DUHRtdXZZSWFkeGdE 
●day 15 任务以及具体安排:https://docs.qq.com/doc/DUHN0ZVJuRmVYeWNv 
●day 16 任务以及具体安排:https://docs.qq.com/doc/DUHBQRm1aSWR4T2NK 
●day 17 任务以及具体安排:https://docs.qq.com/doc/DUFpXY3hBZkpabWFY 
●day 18 任务以及具体安排:https://docs.qq.com/doc/DUFFiVHl3YVlReVlr 
●day 19 周日休息
●day 20 任务以及具体安排:https://docs.qq.com/doc/DUGFRU2V6Z1F4alBH  
●day 21 任务以及具体安排:https://docs.qq.com/doc/DUHl2SGNvZmxqZm1X 
●day 22 任务以及具体安排:https://docs.qq.com/doc/DUHplVUp5YnN1bnBL  
●day 23 任务以及具体安排:https://docs.qq.com/doc/DUFBUQmxpQU1pa29C 
●day 24 任务以及具体安排:https://docs.qq.com/doc/DUEhsb0pUUm1WT2NP  
●day 25 任务以及具体安排:https://docs.qq.com/doc/DUExTYXVzU1BiU2Zl

目录

0039_组合总和

0040_组合总和II

0131_分割回文串


0039_组合总和

package com.question.solve.leetcode.programmerCarl2._08_backtrackingAlgorithms;import java.util.*;public class _0039_组合总和 {
}class Solution0039 {//剪枝优化public List<List<Integer>> combinationSum(int[] candidates, int target) {List<List<Integer>> res = new ArrayList<>();Arrays.sort(candidates); //先进行排序backtracking(res, new ArrayList<>(), candidates, target, 0, 0);return res;}public void backtracking(List<List<Integer>> res, List<Integer> path, int[] candidates, int target, int sum, int idx) {//找到了数字和为 target 的组合if (sum == target) {res.add(new ArrayList<>(path));return;}for (int i = idx; i < candidates.length; i++) {//如果 sum + candidates[i] > target 就终止遍历if (sum + candidates[i] > target) break;path.add(candidates[i]);backtracking(res, path, candidates, target, sum + candidates[i], i);path.remove(path.size() - 1); //回溯,移除路径 path 最后一个元素}}
}class Solution0039_2 {public List<List<Integer>> combinationSum(int[] candidates, int target) {int len = candidates.length;List<List<Integer>> res = new ArrayList<>();if (len == 0) {return res;}Deque<Integer> path = new ArrayDeque<>();dfs(candidates, 0, len, target, path, res);return res;}/*** @param candidates 候选数组* @param begin      搜索起点* @param len        冗余变量,是 candidates 里的属性,可以不传* @param target     每减去一个元素,目标值变小* @param path       从根结点到叶子结点的路径,是一个栈* @param res        结果集列表*/private void dfs(int[] candidates, int begin, int len, int target, Deque<Integer> path, List<List<Integer>> res) {//target 为负数和 0 的时候,不再产生新的孩子结点if (target < 0) {return;}if (target == 0) {res.add(new ArrayList<>(path));return;}//重点理解这里从 begin 开始搜索的语意for (int i = begin; i < len; i++) {path.addLast(candidates[i]);//注意:由于每一个元素可以重复使用,下一轮搜索的起点依然是 i,这里非常容易弄错dfs(candidates, i, len, target - candidates[i], path, res);//状态重置path.removeLast();}}
}

0040_组合总和II

package com.question.solve.leetcode.programmerCarl2._08_backtrackingAlgorithms;import java.util.*;public class _0040_组合总和II {public static void main(String[] args) {int[] candidates = new int[]{10, 1, 2, 7, 6, 1, 5};int target = 8;Solution0040_3 solution = new Solution0040_3();List<List<Integer>> res = solution.combinationSum2(candidates, target);System.out.println("输出 => " + res);}
}class Solution0040 {//使用标记数组LinkedList<Integer> path = new LinkedList<>();List<List<Integer>> ans = new ArrayList<>();boolean[] used;int sum = 0;public List<List<Integer>> combinationSum2(int[] candidates, int target) {used = new boolean[candidates.length];//加标志数组,用来辅助判断同层节点是否已经遍历Arrays.fill(used, false);//为了将重复的数字都放到一起,所以先进行排序Arrays.sort(candidates);backTracking(candidates, target, 0);return ans;}private void backTracking(int[] candidates, int target, int startIndex) {if (sum == target) {ans.add(new ArrayList(path));}for (int i = startIndex; i < candidates.length; i++) {if (sum + candidates[i] > target) {break;}//出现重复节点,同层的第一个节点已经被访问过,所以直接跳过if (i > 0 && candidates[i] == candidates[i - 1] && !used[i - 1]) {continue;}used[i] = true;sum += candidates[i];path.add(candidates[i]);//每个节点仅能选择一次,所以从下一位开始backTracking(candidates, target, i + 1);used[i] = false;sum -= candidates[i];path.removeLast();}}
}class Solution0040_2 {//不使用标记数组List<List<Integer>> res = new ArrayList<>();LinkedList<Integer> path = new LinkedList<>();int sum = 0;public List<List<Integer>> combinationSum2(int[] candidates, int target) {//为了将重复的数字都放到一起,所以先进行排序Arrays.sort(candidates);backTracking(candidates, target, 0);return res;}private void backTracking(int[] candidates, int target, int start) {if (sum == target) {res.add(new ArrayList<>(path));return;}for (int i = start; i < candidates.length && sum + candidates[i] <= target; i++) {//正确剔除重复解的办法//跳过同一树层使用过的元素if (i > start && candidates[i] == candidates[i - 1]) {continue;}sum += candidates[i];path.add(candidates[i]);// i+1 代表当前组内元素只选取一次backTracking(candidates, target, i + 1);int temp = path.getLast();sum -= temp;path.removeLast();}}
}class Solution0040_3 {public List<List<Integer>> combinationSum2(int[] candidates, int target) {int len = candidates.length;List<List<Integer>> res = new ArrayList<>();if (len == 0) {return res;}//关键步骤Arrays.sort(candidates);Deque<Integer> path = new ArrayDeque<>(len);dfs(candidates, len, 0, target, path, res);return res;}/*** @param candidates 候选数组* @param len        冗余变量* @param begin      从候选数组的 begin 位置开始搜索* @param target     表示剩余,这个值一开始等于 target,基于题目中说明的"所有数字(包括目标数)都是正整数"这个条件* @param path       从根结点到叶子结点的路径* @param res*/private void dfs(int[] candidates, int len, int begin, int target, Deque<Integer> path, List<List<Integer>> res) {if (target == 0) {res.add(new ArrayList<>(path));return;}for (int i = begin; i < len; i++) {//大剪枝:减去 candidates[i] 小于 0,减去后面的 candidates[i + 1]、candidates[i + 2] 肯定也小于 0,因此用 breakif (target - candidates[i] < 0) {break;}//小剪枝:同一层相同数值的结点,从第 2 个开始,候选数更少,结果一定发生重复,因此跳过,用 continueif (i > begin && candidates[i] == candidates[i - 1]) {continue;}path.addLast(candidates[i]);//调试语句 ①//System.out.println("递归之前 => " + path + ",剩余 = " + (target - candidates[i]));// 因为元素不可以重复使用,这里递归传递下去的是 i + 1 而不是 idfs(candidates, len, i + 1, target - candidates[i], path, res);path.removeLast();//调试语句 ②//System.out.println("递归之后 => " + path + ",剩余 = " + (target - candidates[i]));}}
}

0131_分割回文串

package com.question.solve.leetcode.programmerCarl2._08_backtrackingAlgorithms;import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;public class _0131_分割回文串 {
}class Solution0131 {List<List<String>> lists = new ArrayList<>();Deque<String> deque = new LinkedList<>();public List<List<String>> partition(String s) {backTracking(s, 0);return lists;}private void backTracking(String s, int startIndex) {//如果起始位置大于s的大小,说明找到了一组分割方案if (startIndex >= s.length()) {lists.add(new ArrayList(deque));return;}for (int i = startIndex; i < s.length(); i++) {//如果是回文子串,则记录if (isPalindrome(s, startIndex, i)) {String str = s.substring(startIndex, i + 1);deque.addLast(str);} else {continue;}//起始位置后移,保证不重复backTracking(s, i + 1);deque.removeLast();}}//判断是否是回文串private boolean isPalindrome(String s, int startIndex, int end) {for (int i = startIndex, j = end; i < j; i++, j--) {if (s.charAt(i) != s.charAt(j)) {return false;}}return true;}
}class Solution0131_2 {//回溯+动态规划优化回文串判断List<List<String>> result;LinkedList<String> path;boolean[][] dp;public List<List<String>> partition(String s) {result = new ArrayList<>();char[] str = s.toCharArray();path = new LinkedList<>();dp = new boolean[str.length + 1][str.length + 1];isPalindrome(str);backtracking(s, 0);return result;}public void backtracking(String str, int startIndex) {if (startIndex >= str.length()) {//如果起始位置大于s的大小,说明找到了一组分割方案result.add(new ArrayList<>(path));} else {for (int i = startIndex; i < str.length(); ++i) {if (dp[startIndex][i]) {//是回文子串,进入下一步递归//先将当前子串保存入pathpath.addLast(str.substring(startIndex, i + 1));//起始位置后移,保证不重复backtracking(str, i + 1);path.pollLast();} else {//不是回文子串,跳过continue;}}}}//通过动态规划判断是否是回文串,参考动态规划篇 52 回文子串public void isPalindrome(char[] str) {for (int i = 0; i <= str.length; ++i) {dp[i][i] = true;}for (int i = 1; i < str.length; ++i) {for (int j = i; j >= 0; --j) {if (str[j] == str[i]) {if (i - j <= 1) {dp[j][i] = true;} else if (dp[j + 1][i - 1]) {dp[j][i] = true;}}}}}
}

这篇关于代码随想录-算法训练营day27【回溯03:组合总和、分割回文串】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/947426

相关文章

Java中的雪花算法Snowflake解析与实践技巧

《Java中的雪花算法Snowflake解析与实践技巧》本文解析了雪花算法的原理、Java实现及生产实践,涵盖ID结构、位运算技巧、时钟回拨处理、WorkerId分配等关键点,并探讨了百度UidGen... 目录一、雪花算法核心原理1.1 算法起源1.2 ID结构详解1.3 核心特性二、Java实现解析2.

Java中调用数据库存储过程的示例代码

《Java中调用数据库存储过程的示例代码》本文介绍Java通过JDBC调用数据库存储过程的方法,涵盖参数类型、执行步骤及数据库差异,需注意异常处理与资源管理,以优化性能并实现复杂业务逻辑,感兴趣的朋友... 目录一、存储过程概述二、Java调用存储过程的基本javascript步骤三、Java调用存储过程示

Visual Studio 2022 编译C++20代码的图文步骤

《VisualStudio2022编译C++20代码的图文步骤》在VisualStudio中启用C++20import功能,需设置语言标准为ISOC++20,开启扫描源查找模块依赖及实验性标... 默认创建Visual Studio桌面控制台项目代码包含C++20的import方法。右键项目的属性:

MySQL数据库的内嵌函数和联合查询实例代码

《MySQL数据库的内嵌函数和联合查询实例代码》联合查询是一种将多个查询结果组合在一起的方法,通常使用UNION、UNIONALL、INTERSECT和EXCEPT关键字,下面:本文主要介绍MyS... 目录一.数据库的内嵌函数1.1聚合函数COUNT([DISTINCT] expr)SUM([DISTIN

Java实现自定义table宽高的示例代码

《Java实现自定义table宽高的示例代码》在桌面应用、管理系统乃至报表工具中,表格(JTable)作为最常用的数据展示组件,不仅承载对数据的增删改查,还需要配合布局与视觉需求,而JavaSwing... 目录一、项目背景详细介绍二、项目需求详细介绍三、相关技术详细介绍四、实现思路详细介绍五、完整实现代码

Go语言代码格式化的技巧分享

《Go语言代码格式化的技巧分享》在Go语言的开发过程中,代码格式化是一个看似细微却至关重要的环节,良好的代码格式化不仅能提升代码的可读性,还能促进团队协作,减少因代码风格差异引发的问题,Go在代码格式... 目录一、Go 语言代码格式化的重要性二、Go 语言代码格式化工具:gofmt 与 go fmt(一)

HTML5实现的移动端购物车自动结算功能示例代码

《HTML5实现的移动端购物车自动结算功能示例代码》本文介绍HTML5实现移动端购物车自动结算,通过WebStorage、事件监听、DOM操作等技术,确保实时更新与数据同步,优化性能及无障碍性,提升用... 目录1. 移动端购物车自动结算概述2. 数据存储与状态保存机制2.1 浏览器端的数据存储方式2.1.

基于 HTML5 Canvas 实现图片旋转与下载功能(完整代码展示)

《基于HTML5Canvas实现图片旋转与下载功能(完整代码展示)》本文将深入剖析一段基于HTML5Canvas的代码,该代码实现了图片的旋转(90度和180度)以及旋转后图片的下载... 目录一、引言二、html 结构分析三、css 样式分析四、JavaScript 功能实现一、引言在 Web 开发中,

Python如何去除图片干扰代码示例

《Python如何去除图片干扰代码示例》图片降噪是一个广泛应用于图像处理的技术,可以提高图像质量和相关应用的效果,:本文主要介绍Python如何去除图片干扰的相关资料,文中通过代码介绍的非常详细,... 目录一、噪声去除1. 高斯噪声(像素值正态分布扰动)2. 椒盐噪声(随机黑白像素点)3. 复杂噪声(如伪

Java Spring ApplicationEvent 代码示例解析

《JavaSpringApplicationEvent代码示例解析》本文解析了Spring事件机制,涵盖核心概念(发布-订阅/观察者模式)、代码实现(事件定义、发布、监听)及高级应用(异步处理、... 目录一、Spring 事件机制核心概念1. 事件驱动架构模型2. 核心组件二、代码示例解析1. 事件定义