LeetCode 39. 组合总和 40.组合总和II 131.分割回文串
欢迎关注个人公众号:爱喝可可牛奶
LeetCode 39. 组合总和 40.组合总和II 131.分割回文串
LeetCode 39. 组合总和
分析
回溯可看成对二叉树节点进行组合枚举,分为横向和纵向
每次往sum添加新元素时,必须明确从can哪个位置开始,定义变量pos
返回条件 sum == target 或 sum > target; 横向结束条件 没有新元素可以添加了即pos<can.length;
bt(can, sum, tar, pos){
if(sum == tar) add return;
if(sum > tar) pos++ return;
for(int i = pos; i < can.len;i++){
sum+=can[pos];
bt(can, sum, tar, i);
sum-=can[pos];
}
}
这个回溯考虑sum > tar时, pos++不应该写在第3行,这样导致回溯减掉的元素值与递归添加的不一样。而应该放在第4行for()中,只有当纵向回溯结束时(也就是很多个sum+=can[i]导致return后),横向遍历才会往右移动;回溯第n个can[i] 回溯第n-1个can[i];
剪枝
一次回溯只能抵消一层递归;每次return只是从已经添加进sum的众多can[i]中减掉一个
举个栗子:
sum+= n个can[i],回溯一次还剩n-1个can[i];这时要i++了;但是剩下的sum和这个i++后的新can[i]加起来可能也会超过tar,这步操作可以剪枝,避免进入新can[i]的递归;
for (int i = pos; i < candidates.size() && sum + candidates[i] <= target; i++)
代码
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList();
public List<List<Integer>> combinationSum(int[] candidates, int target) {
Arrays.sort(candidates); // 先进行排序
backtracking(candidates, target, 0, 0);
return res;
}
public void backtracking(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(candidates, target, sum + candidates[i], i);
path.removeLast(); // 回溯,移除路径 path 最后一个元素
}
}
}
LeetCode 40.组合总和II
分析
在原有基础上设限每个数字在每个组合中只能使用 一次 且不包含重复的组合
Arrays升序;纵向遍历时就要i++;Set去重
Set去重超时了!!! 要在添加集合的时候就判断是否重复,取res中最后一个path和当前满足条件的path比较 也不行
纵向递归不需要去重,横向递归时采用去重
剪枝
代码
class Solution {
List<List<Integer>> res = new LinkedList();
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;
}
public void backtracking(int[] candidates, int target, int idx) {
// 找到了数字和为 target 的组合
if (sum == target) {
res.add(new LinkedList<>(path));
return;
}
for (int i = idx; i < candidates.length && sum + candidates[i] <= target; i++) {
// 要对横向遍历时使用过的元素进行跳过 因为一样的元素在深度递归时已经把包含此元素的所有可能结果全部枚举过了
if (i > idx && candidates[i] == candidates[i - 1]) {
continue;
}
path.add(candidates[i]);
sum += candidates[i];
//System.out.println("sum="+sum);
//i++;
backtracking(candidates, target, i+1);
//i--;
//sum -= candidates[i];
sum-=path.getLast();
path.removeLast(); // 回溯,移除路径 path 最后一个元素
}
}
}
LeetCode 131.分割回文串
分析
切割子串,保证每个子串都是 回文串
找到所有的子串组合,判断子串是否是回文串,根据索引切割 startIndex endIndex if(start-end) is ; res.add
代码
class Solution {
List<List<String>> res = new ArrayList<>();
LinkedList<String> path = new LinkedList<>();
public List<List<String>> partition(String s) {
backTracking(s, 0);
return res;
}
private void backTracking(String s, int startIndex) {
//如果起始位置大于s的大小,说明找到了一组分割方案
if (startIndex >= s.length()) {
res.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();
}
}
//判断是否是回文串
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;
}
}
总结
- 题目给定的数据集如果使用数组的方式,要判断是否有序,没有说明有序最好视情排序
- 回溯横向移动的时机一定是某个纵向递归结束
- 看清题目要求,将串的所有子串都分割成回文子串
- 横向遍历逻辑 纵向递归startIndex++逻辑 回溯逻辑
LeetCode 39. 组合总和 40.组合总和II 131.分割回文串的更多相关文章
- LeetCode 131. 分割回文串(Palindrome Partitioning)
131. 分割回文串 131. Palindrome Partitioning 题目描述 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. LeetC ...
- Leetcode之回溯法专题-131. 分割回文串(Palindrome Partitioning)
Leetcode之回溯法专题-131. 分割回文串(Palindrome Partitioning) 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. ...
- Leetcode 131.分割回文串
分割回文串 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. 示例: 输入: "aab" 输出: [ ["aa" ...
- LeetCode 131. 分割回文串(Palindrome Partitioning)
题目描述 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. 示例: 输入: "aab" 输出: [ ["aa" ...
- Java实现 LeetCode 131 分割回文串
131. 分割回文串 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. 示例: 输入: "aab" 输出: [ ["aa ...
- Java实现 LeetCode 132 分割回文串 II(二)
132. 分割回文串 II 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回符合要求的最少分割次数. 示例: 输入: "aab" 输出: 1 解释: 进行一 ...
- 【LEETCODE】72、分割回文串 III 第1278题
package y2019.Algorithm.dynamicprogramming.hard; /** * @Auther: xiaof * @Date: 2019/12/11 08:59 * @D ...
- LeetCode 132. 分割回文串 II(Palindrome Partitioning II)
题目描述 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回符合要求的最少分割次数. 示例: 输入: "aab" 输出: 1 解释: 进行一次分割就可将 s ...
- [Swift]LeetCode132. 分割回文串 II | Palindrome Partitioning II
Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...
- 分割回文串 II · Palindrome Partitioning II
[抄题]: 给定一个字符串s,将s分割成一些子串,使每个子串都是回文. 返回s符合要求的的最少分割次数. [思维问题]: 不知道要用预处理字符串降低复杂度 [一句话思路]: 先把预处理获得s中回文串的 ...
随机推荐
- Django基础笔记10(前端展示)
Ajax使用 $.ajax({ url:xxx, type:xxx, dadaType:xxx, data:{...} }) $.post(url,data,callbackFunction,data ...
- 【Java SE进阶】Day11 网络编程、TCP应用程序
一.网络编程入门 1.软件架构 C/S:QQ.迅雷 B/S 共同点:都离不开网络的支持 网络编程:在一定的协议下,实现两台计算机通信 2.网络通信协议 通信协议:需遵守的规则,只有遵守才能通信 主要包 ...
- HDOJFatmouse肥鼠交易//c++控制保留小数
贪心算法.我就不贴题了//no.1009 但是我的代码运行超时了-改了好久都不对- 看别人代码,顺便学习c++控制保留小数怎么操作; 我的错误代码:(时间占用可能是多次调用findmax造成的) #i ...
- web框架推导 wsgiref模块 jinja2模板语法 django框架简介 django基本操作
目录 纯手撸web框架 web框架的本质 手写web框架 存在的问题 基于wsgiref模块 基本介绍 推导流程 代码封装优化 总结 动静态网页 jinja2模块 前端.后端.数据库三者联动 推导流程 ...
- 一个sql和C#代码结合的分组求和的查询
业务描述: 业务主表(tab_main 主键 id), 供应商名称(supplier), 金额(amount 需要统计求和),还有分类( 有单独的表categoryid),集中采购标记字段(tend ...
- python3使用OCR识别图片
放假三天,闲来无事,想学下python爬虫.本想跟着网上教程操作一遍,奈何安装使用过程中出现一堆问题,并且在网上搜了一堆复制黏贴的答案,关键都不能起作用,最后终于找到一篇生效,为了以后不至于再经历这种 ...
- Python 文件操作(IO 技术)
目录 Python 文件操作(IO 技术) 文本文件和二进制文件 文件操作相关模块概述 建文件对象 open() 文本文件的写入 write()/writelines()写入数据 close()关闭文 ...
- Windows 安装 Anaconda
下载 anaconda 官网 https://repo.anaconda.com/archive/ 国内镜像 https://mirrors.bfsu.edu.cn/anaconda/archive/ ...
- AJAX容易出错地方,错误处理
myajax.js //创建路由器对象 const express=require('express'); //引入连接池模块 const pool=require('../pool.js'); ...
- 今天遇到的报错Babel noteThe code generator has deoptimised the styling of ...as it exceeds the max of 500KB.
解决办法如下: { test: /.js$/, exclude: /node_modules/, use: 'babel-loader' } 然并卵,我已经设置了这个东西了,突然发现我的文件并不在no ...