欢迎关注个人公众号:爱喝可可牛奶

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;
}
}

总结

  1. 题目给定的数据集如果使用数组的方式,要判断是否有序,没有说明有序最好视情排序
  2. 回溯横向移动的时机一定是某个纵向递归结束
  3. 看清题目要求,将串的所有子串都分割成回文子串
  4. 横向遍历逻辑 纵向递归startIndex++逻辑 回溯逻辑

LeetCode 39. 组合总和 40.组合总和II 131.分割回文串的更多相关文章

  1. LeetCode 131. 分割回文串(Palindrome Partitioning)

    131. 分割回文串 131. Palindrome Partitioning 题目描述 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. LeetC ...

  2. Leetcode之回溯法专题-131. 分割回文串(Palindrome Partitioning)

    Leetcode之回溯法专题-131. 分割回文串(Palindrome Partitioning) 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. ...

  3. Leetcode 131.分割回文串

    分割回文串 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. 示例: 输入: "aab" 输出: [ ["aa" ...

  4. LeetCode 131. 分割回文串(Palindrome Partitioning)

    题目描述 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. 示例: 输入: "aab" 输出: [ ["aa" ...

  5. Java实现 LeetCode 131 分割回文串

    131. 分割回文串 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回 s 所有可能的分割方案. 示例: 输入: "aab" 输出: [ ["aa ...

  6. Java实现 LeetCode 132 分割回文串 II(二)

    132. 分割回文串 II 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回符合要求的最少分割次数. 示例: 输入: "aab" 输出: 1 解释: 进行一 ...

  7. 【LEETCODE】72、分割回文串 III 第1278题

    package y2019.Algorithm.dynamicprogramming.hard; /** * @Auther: xiaof * @Date: 2019/12/11 08:59 * @D ...

  8. LeetCode 132. 分割回文串 II(Palindrome Partitioning II)

    题目描述 给定一个字符串 s,将 s 分割成一些子串,使每个子串都是回文串. 返回符合要求的最少分割次数. 示例: 输入: "aab" 输出: 1 解释: 进行一次分割就可将 s ...

  9. [Swift]LeetCode132. 分割回文串 II | Palindrome Partitioning II

    Given a string s, partition s such that every substring of the partition is a palindrome. Return the ...

  10. 分割回文串 II · Palindrome Partitioning II

    [抄题]: 给定一个字符串s,将s分割成一些子串,使每个子串都是回文. 返回s符合要求的的最少分割次数. [思维问题]: 不知道要用预处理字符串降低复杂度 [一句话思路]: 先把预处理获得s中回文串的 ...

随机推荐

  1. .net6+wpf制作指定局域网ip无法上网的arp欺诈工具

    摘一段来自网上的arp欺诈解释:ARP欺骗(ARP spoofing),又称ARP毒化(ARP poisoning,网络上多译为ARP病毒)或ARP攻击,是针对以太网地址解析协议(ARP)的一种攻击技 ...

  2. 彻底理解Python中的闭包和装饰器(上)

    什么是闭包 闭包(Closure)其实并不是Python独有的特性,很多语言都有对闭包的支持.(当然,因为Python是笔者除C/C++之外学习的第二门语言,所以也是第一次遇到闭包.)简而言之,闭包实 ...

  3. day05-功能实现04

    家居网购项目实现04 以下皆为部分代码,详见 https://github.com/liyuelian/furniture_mall.git 10.功能09-后台管理 删除家居 10.1需求分析/图解 ...

  4. 9、IDEA回退Git版本

    转载自 在工作中有时候会要求我们将以前提交的代码新开一个分支,而把之前提交的分支回退到以前某个版本. 1.通过IDEA查看Git历史记录,复制当前版本号. 2.记录当前版本号后,再复制你要回退的版本号 ...

  5. java注解基础知识整理

    目录 1.注解的定义 1.1.定义一个注解 1.2.注解的使用 2.JDK内置注解 2.1.java.lang包下的注释类型 2.2.元注解 2.3.Deprecated注解 3.在注解中定义属性 3 ...

  6. Python二维码扫描

    原文链接:https://blog.easyctf.cn/Moxin/59365.html 模块准备 1.pyzbar pip install pyzbar 2.PIL 注意:PIL只支持Python ...

  7. Asp-Net-Core-搭建ELK日志平台-Docker-Compose版本

    title: Asp.Net Core 搭建ELK日志平台(Docker-Compose版本) date: 2022-09-27 15:16:59 tags: - .NET 由于暂时用不上Logsta ...

  8. 深入探究Java中的对象类型变量声明操作——在声明对象时,系统究竟做了什么?

    深入探究Java中的对象类型变量声明操作--在声明对象时,系统究竟做了什么? 摘要:本文主要对Java中的对象类型变量的声明的底层原理做了探究. 目录 深入探究Java中的对象类型变量声明操作--在声 ...

  9. Linux的串口非标准波特率设置更改

    用的是全志的R528 SDK,Linux内核是5.4,新增加一个250000的非标准波特率 参考网络大神文档,实践并记录宝贵的经验. 方法: 1.修改内核的/include/uapi/asm-gene ...

  10. VMware vSphere vCenter ServerAppliance 7.0安装配置

    VMware vSphere vCenter ServerAppliance 7.0安装配置 环境说明: 1.将vCenter ServerAppliance部署在ESXi主机上,安装配置好ESXi主 ...