2023.4.11 复原IP地址
也是进行切割操作。思考一下终止条件:我们的切割位到达了字符串末尾。同时还有一些小要求,即每个小子串处于0-255之间,如果超过一位的话,不能由0开头。
同时,回溯的时候也需要控制我们的删除区域。
class Solution {
List<String> res = new ArrayList<>();
StringBuilder sb = new StringBuilder();
int splitTimes = 0;
public List<String> restoreIpAddresses(String s) {
backTracking(s,0);
return res;
}
public void backTracking(String s,int start){
if(start == s.length() && splitTimes == 4){
res.add(sb.toString());
return;
}
else if(start == s.length() || splitTimes == 4){
return;
}
for(int i = start;i<s.length() && i - start <=2;i++){
String str = s.substring(start,i+1);
//检查str是否符合要求。
if(Integer.parseInt(str)> 255){//不能大于255
break;
}
if(str.length() > 1 && str.charAt(0) == '0'){//不能有前导0
break;
}
sb.append(str);
if(splitTimes < 3){
sb.append(".");
}
splitTimes++;
//进入递归
backTracking(s,i+1);
//回溯
splitTimes--;
sb.delete(start + splitTimes,i+splitTimes+2);
}
}
}
2023.4.11 子集
如何确定终止条件?不需要终止条件!因为子集需要我们遍历整个节点,而之前的求组合之所以有终止条件是因为我们需要求得是叶子结点。
这个子集就是标准的回溯模板
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
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.removeLast();
}
}
}
2023.4.11 子集Ⅱ
排序后去重操作,和们之前的数组总和Ⅱ有点类似。
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(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++){
if( i>start && nums[i] == nums[i-1]){//去重操作,同一层不能有重复的数字。否则会出现相同的结果
continue;
}
path.add(nums[i]);
backTracking(nums,i+1);
path.removeLast();
}
}
}