这一题是今天最难的一题,首先需要分割字符串,然后还要判断分割出来的子串是否合法。这里分割字符串需要解决的问题有:如何只分四段,而且在这四段中间加上逗点。其次就是判断子串的合法性。
解决分割字符串和加逗点的问题:在之前的二叉树章节,收集路径总和是用stringbuilder收集路径值,在终止条件中遍历stringbuilder在其中加上箭头。而在本题中,直接在单层逻辑处理中对字符串作处理,在符合条件的分割出来的子串后面加上逗点构成新的字符串。终止条件的判断逻辑也是使用了逗点,这里用逗点数作为终止条件,当存在三个逗点后,且最后的子串也符合条件的话,则将整个加了逗点的新字符串放入结果集中,若是不符合条件,则进行回溯,同时删除之前添加的逗点,重新分割子串。
class Solution {
List<String> res=new ArrayList();
int pointsum=0;
public List<String> restoreIpAddresses(String s) {
if(s.length()>12){
return res;
}
backtracking(s,0);
return res;
}
public void backtracking(String s,int startindex){
//startindex 搜索的起始位置,pointsum逗点的数量
if(pointsum==3){
//判断第四段子串是否有效,有效则放进结果中
if(isvalid(s,startindex,s.length()-1)){
res.add(s);
}
return;
}
for(int i=startindex;i<s.length();i++){
if(isvalid(s,startindex,i)){
s=s.substring(0,i+1)+"."+s.substring(i+1);
pointsum++;
//切割符合条件的情况下才往下递归
backtracking(s,i+2);
pointsum--;
s=s.substring(0,i+1)+s.substring(i+2);
}else{
break;
}
}
}
public boolean isvalid(String s,int start,int end){
if(start>end){//防止startindex越界到字符串后
return false;
}
if(s.charAt(start)=='0'&&start!=end){
return false;
}
int num=0;
for(int i=start;i<=end;i++){
num=num*10+(s.charAt(i)-'0');
if(num>255){
return false;
}
}
return true;
}
}
这一题只需收集每一个路径数组即可,不需要再终止条件中收集最后的组合。使用回溯模板方法
class Solution {
List<List<Integer>> res=new ArrayList();
List<Integer> path=new ArrayList();
public List<List<Integer>> subsets(int[] nums) {
res.add(new ArrayList(path));
backtracking(nums,0);
return res;
}
public void backtracking(int[] nums,int startindex){
if(startindex>=nums.length){
return;
}
for(int i=startindex;i<nums.length;i++){
path.add(nums[i]);
res.add(new ArrayList(path));
backtracking(nums,i+1);
path.remove(path.size()-1);
}
}
}
这一题是子集和昨天的需要去重的组合问题的结合版本。这里去重同样使用昨天的方法,使用一个boolean类型的used数组来进行树层去重,而不进行树枝去重。使用回溯模版方法加上标识数组。同时,这里要注意要对数组进行排序,这里的标识数组使用的前提是目标数组有序
class Solution {
List<List<Integer>> res=new ArrayList();
List<Integer> path=new ArrayList();
boolean[] used;
public List<List<Integer>> subsetsWithDup(int[] nums) {
used=new boolean[nums.length];
Arrays.fill(used,false);
Arrays.sort(nums);
res.add(new ArrayList(path));
backtracking(nums,0,used);
return res;
}
public void backtracking(int[] nums,int startindex,boolean[] used){
if(startindex>=nums.length){
return;
}
for(int i=startindex;i<nums.length;i++){
if(i>0&&nums[i]==nums[i-1]&&used[i-1]!=true){
continue;
}
path.add(nums[i]);
used[i]=true;
res.add(new ArrayList(path));
backtracking(nums,i+1,used);
path.remove(path.size()-1);
used[i]=false;
}
}
}