算法笔记|Day21回溯算法III
☆☆☆☆☆leetcode 93.复原IP地址
题目链接:leetcode 93.复原IP地址
题目分析
分割字符串采用回溯算法,把所有可能性搜出来。本题中IP地址共四个整数,且每个整数要求合法,中间需要加三个“.”,故可以将加点数point=3作为终止条件,同时最后一个数要合法满足规范才加到res结果中。判断是否合法需要注意:不能超过三位数,且两位鼠标和三位数首位前不含0,最大不超过255,依次设置条件判断。
代码
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 start,int point){
if(point==3){
if(isvalid(s,start,s.length()-1)){
res.add(s);
}
return;
}
for(int i=start;i<s.length();i++){
if(isvalid(s,start,i)){
s=s.substring(0,i+1)+"."+s.substring(i+1);
point++;
backtracking(s,i+2,point);
s=s.substring(0,i+1)+s.substring(i+2);
point--;
}else
break;
}
}
public boolean isvalid(String s,int start,int end){
if(start>end||end-start>2)
return false;
if(s.charAt(start)=='0'&&start!=end)
return false;
int num;
if(end-start==2){
num=(s.charAt(start)-'0')*100+(s.charAt(start+1)-'0')*10+(s.charAt(start+2)-'0');
if(num>255)
return false;
}
return true;
}
}
☆☆☆☆☆leetcode 78.子集
题目链接:leetcode 78.子集
题目分析
子集问题和组合问题、分割问题类似,采用回溯方法,若都抽象为一棵树的话,那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点,所以要将每一个结果加入到res数组中。
代码
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 start){
res.add(new ArrayList(path));
for(int i=start;i<nums.length;i++){
path.add(nums[i]);
backtracking(nums,i+1);
path.remove(path.size()-1);
}
}
}
☆☆☆☆☆leetcode 90.子集II
题目链接:leetcode 90.子集II
题目分析
此题在求子集的基础上需要增加去重的逻辑,采用了used数组,若该元素在本轮回溯遍历(树层)中用到过赋值为1,后续不再使用,回溯时恢复为0;但在递归遍历(树枝)中用到过,还可以继续使用。
代码
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,0,used);
return res;
}
public void backtracking(int nums[],int start,int used[]){
res.add(new ArrayList(path));
for(int i=start;i<nums.length;i++){
if(i>0&&nums[i]==nums[i-1]&&used[i-1]==0)
continue;
path.add(nums[i]);
used[i]=1;
backtracking(nums,i+1,used);
path.remove(path.size()-1);
used[i]=0;
}
}
}