1、分割回文串
2、复原IP地址
3、子集
给你一个字符串 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 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 ‘.’ 分隔。
给定一个只包含数字的字符串 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;}
}
给你一个整数数组 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();}}
}
如果把 子集问题、组合问题、分割问题都抽象为一棵树的话,那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!