day30【代码随想录】回溯之分割回文串、复原IP地址、子集
创始人
2024-05-02 14:24:39
0

文章目录

  • 前言
  • 一、分割回文串(力扣131)
  • 二、复原IP地址(力扣93)
  • 三、子集(力扣78)
  • 总结


前言

1、分割回文串
2、复原IP地址
3、子集


一、分割回文串(力扣131)

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

回文串 是正着读和反着读都一样的字符串。
在这里插入图片描述
思路:
关键在于[startIndex,i] 这个区间就是我们切割的子串【重点!!!】
startIndex就相当于是切割线!!!
在这里插入图片描述
整体步骤:
1、如何模拟切割线
2、递归如何终止
3、如何获取子串
4、判断回文

class Solution {List> res = new ArrayList<>();LinkedList paths = new LinkedList<>();public List> partition(String s) {backtracking(s,0);return res;}public void backtracking(String s,int startIndex){if(startIndex==s.length()){res.add(new ArrayList<>(paths));return ;}for(int i=startIndex;iif(isPalinderome(s,startIndex,i)){String str = s.substring(startIndex,i+1);paths.add(str);}else{continue;}backtracking(s,i+1);paths.removeLast();//回溯}}public boolean isPalinderome(String s,int start,int end){for(int i=start,j=end;iif(s.charAt(i)!=s.charAt(j)){return false;}}return true;}
}

在这里插入图片描述

二、复原IP地址(力扣93)

有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 ‘.’ 分隔。

  • 例如:“0.1.2.201” 和 “192.168.1.1” 是 有效 IP 地址,但是 “0.011.255.245”、“192.168.1.312” 和 “192.168@1.1” 是 无效 IP 地址。

给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 ‘.’ 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。

在这里插入图片描述
思路:
在这里插入图片描述
与切割回文串类似:
关键在于切割 切割出来的子串区间 [stratIndex,i] 以及一些字符串的拼接操作,增加"." 判断子串是否合法等等

结束判断:
1、“.”逗点数量已经==3时,需要判断最后一段截取的子串是否合法,如果合法,收集结果

字符串拼接:
1、如果当前截取的子串合法
2、拼接子串(加“.”)
3、递归 (细节:参数不再是i+1 而是i+2)
4、回溯(子串也要退回之前的状态 把“.”去掉)

判断子串是否合法:
1、两位数及以上时 第一位如果为0 不合法
2、包含除0-9以外的其他字符 不合法
3、数值大于255 不合法

class Solution {List res = new ArrayList<>();public List restoreIpAddresses(String s) {if(s.length()>12) return res;backtracking(s,0,0);return res;}public void backtracking(String s,int startIndex,int pointSum){ if(pointSum==3){//判断最后一个部分是不是合法if(isValid(s,startIndex,s.length()-1)){//左闭右闭区间//加入结果集    res.add(s);}return ;}for(int i=startIndex;i//判断所截取子串是否合法if(isValid(s,startIndex,i)){s=s.substring(0,i+1)+"."+s.substring(i+1);//插入逗号pointSum++;backtracking(s,i+2,pointSum);pointSum--;//删除逗号s=s.substring(0,i+1)+s.substring(i+2);}else{continue;}}}public boolean isValid(String s,int start,int end){if(start>end){return false;}if(s.charAt(start)=='0'&& start!=end){return false;}int num=0;for(int i=start;i<=end;i++){if(s.charAt(i)>'9' || s.charAt(i)<'0'){return false;}num = num*10+(s.charAt(i)-'0');if(num>255)return false;}return true;}
}

在这里插入图片描述

三、子集(力扣78)

给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。

解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

在这里插入图片描述
以示例中nums = [1,2,3]为例把求子集抽象为树型结构,如下:
在这里插入图片描述
求取子集问题,不需要任何剪枝!因为子集就是要遍历整棵树。
遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合。

class Solution {List> res = new ArrayList<>();LinkedList paths = new LinkedList<>();public List> subsets(int[] nums) {backtracking(nums,0);return res;}public void backtracking(int[] nums,int startIndex){res.add(new ArrayList<>(paths)); //遍历这棵树的时候,把所有结点记录下来if(startIndex==nums.length){return ;}for(int i=startIndex;ipaths.add(nums[i]);backtracking(nums,i+1);paths.removeLast();}}
}

在这里插入图片描述


总结

如果把 子集问题、组合问题、分割问题都抽象为一棵树的话,那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!

相关内容

热门资讯

前端-session、jwt 目录:   (1)session (2&#x...
linux入门---制作进度条 了解缓冲区 我们首先来看看下面的操作: 我们首先创建了一个文件并在这个文件里面添加了...
关于测试,我发现了哪些新大陆 关于测试 平常也只是听说过一些关于测试的术语,但并没有使用过测试工具。偶然看到编程老师...
前缀和与对数器与二分法 1. 前缀和 假设有一个数组,我们想大量频繁的去访问L到R这个区间的和,...
nodejs:本地安装nvm实... 一、背景-使用不同版本node的原因 vue3+ts、nuxt3版本,node...
JAVA集合知识整理 Java集合知识整理 HashMap相关 HashMap的底层数据结构:jdk1.8之...
无刷直流电机介绍及单片机控制实... 无刷直流电机介绍及单片机控制实例前言基本概念优势与劣势使用寿命基本结构使用单片机控制实例电子调速器&...
fwdiary(2) dp2 1.传纸条  AcWing 275. 传纸条 - AcWing 走两条路,走一条最大的...
常用的DOS命令 常用的DOS命令 DOS(Disk Operating System,磁...
<C++> 类和对象(下) 1.const成员函数将const修饰的“成员函数”称之为const成员函数,cons...