代码随想录刷题记录day 25 复原IP地址+子集问题
参考:代码随想录
93. 复原 IP 地址
思想
用【startIndex,i】表示切割的字符串
如何划分成四段呢?维护一个num,当num==3时,表示切割成了4段,同时这也是递归的终止条件
单层递归中需要对字符串进行拼接
判断字符串是否符合要求主要有以下四点
- left > right return false
- 只有一个字符 return true
- 多个字符 第一个为0 return false
- 有非法字符 或者 大于255 return false
代码
class Solution {
List<String> res=new ArrayList<>();
public List<String> restoreIpAddresses(String s) {
backTracking(s,0,0);
return res;
}
public void backTracking(String s,int startIndex, int num){
//终止条件
if(num==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);
num++;
backTracking(s,i+2,num);
s=s.substring(0,i+1)+s.substring(i+2);
num--;
}else{
break;
}
}
}
public boolean isValid(String s,int left,int right){
//判断是否是有效的ip地址
//【left,right】 表示字符串的区间
if(left>right) return false;
if(left==right) return true;
if(s.charAt(left)=='0' && left!=right) return false;
int num=0;
for(int i=left;i<=right;i++){
//判断是否是非法字符
if(s.charAt(i)>'9' || s.charAt(i)<'0') return false;
//统计是否大于255
num=num*10+(s.charAt(i)-'0');
if(num>255){
return false;
}
}
return true;
}
}
78. 子集
思想
数组中的是互补重复的元素,也不需要去重
在递归返回之前就要收集结果。 当startIndex== num.length 时递归条件终止
代码
class Solution {
List<List<Integer>> res=new ArrayList<>();
List<Integer> path=new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
backTracking(nums,0);
return res;
}
public void backTracking(int[] nums,int startIndex){
res.add(new ArrayList<>(path));
if(startIndex==nums.length) return ;
for(int i=startIndex;i<nums.length;i++){
path.add(nums[i]);
backTracking(nums,i+1);
path.remove(path.size()-1);
}
}
}
90. 子集 II
思想
这题和上一题的不同之处在于数组中包含有重复元素,需要对元素进行去重。
去重又分为了树枝去重,树层去重。此题需要对数层进行去重
用一个used数组记录使用过的数字,0表示未被使用,1表示被使用
代码
class Solution {
List<List<Integer>> res=new ArrayList<>();
List<Integer> path=new ArrayList<>();
public List<List<Integer>> subsetsWithDup(int[] nums) {
int[] used =new int[nums.length];
Arrays.sort(nums);
backTracking(nums,used,0);
return res;
}
public void backTracking(int[] nums,int[] used,int startIndex){
res.add(new ArrayList<>(path));
if(startIndex==nums.length) return;//递归终止终止条件
for(int i=startIndex;i<nums.length;i++){
if(i>0 && nums[i-1]==nums[i] && used[i-1]==0){
continue;
}
path.add(nums[i]);
used[i]=1;
backTracking(nums,used,i+1);
used[i]=0;
path.remove(path.size()-1);
}
}
}