day27-1 ●93.复原IP地址
class Solution {
List<String> result = new ArrayList<>();
public List<String> restoreIpAddresses(String s) {
if(s.length() > 12){
return result;
}
backTracking(s, 0, 0);
return result;
}
// startIndex:搜索的起始位置, pointNum:添加逗点的数量
private void backTracking(String s, int startIndex, int pointNum){
if(pointNum == 3){// 逗点数量为3,分割结束,收集结果
// 判断第四段字符串是否合法,如果合法就放进result中
if(isValid(s, startIndex, s.length() - 1)){
result.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);// 在str后面插入逗点
pointNum++;
backTracking(s, i + 2, pointNum);// 插入逗点之后下一个字串的起始位置为i+2;
pointNum--;
s = s.substring(0, i + 1) + s.substring(i + 2);// 回溯删除逗点
}else{
break;
}
}
}
// 判断字符串s在左闭右闭区间[start, end]所组成的数字是否合法
private Boolean isValid(String s, int start, int end){
if(start > end){
return false;
}
if(s.charAt(start)== '0' && start != end){// 0开头的数字不合法,排除0000
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){// 如果大于255了不合法
return false;
}
}
return true;
}
}
day27-2 ● 78.子集
本题差别
子集问题、组合问题、分割问题的区别
不单只在树的叶子节点的时候收集结果
树形结构
代码实现
class Solution {
List<List<Integer>> result = new ArrayList<>();// 存放符合条件结果的集合
LinkedList<Integer> path = new LinkedList<>();// 用来存放符合条件结果
public List<List<Integer>> subsets(int[] nums) {
subsetsHelper(nums, 0);
return result;
}
private void subsetsHelper(int[] nums, int startIndex){
result.add(new ArrayList<>(path));//「遍历这个树的时候,把所有节点都记录下来,就是要求的子集集合」。
if (startIndex >= nums.length){ //终止条件可不加
return;
}
for (int i = startIndex; i < nums.length; i++){
path.add(nums[i]);
subsetsHelper(nums, i + 1); // i+1: 因为是组合大类问题和顺序无关
path.removeLast();
}
}
}
总结
- 子集问题和组合问题的区别、子集问题和分割问题的区别:
组合问题和分割问题都是收集数的子节点
子集问题是找数的所有节点
day27-3 ●90.子集II
关键在去重
- 横向去重,纵向不去重
树形结构
代码实现
class Solution {
// 使用used
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
boolean[] used;
public List<List<Integer>> subsetsWithDup(int[] nums) {
if(nums.length == 0){
result.add(path);
return result;
}
Arrays.sort(nums);
used = new boolean[nums.length];
backTracking(nums, 0);
return result;
}
private void backTracking(int[] nums, int startIndex){
result.add(new ArrayList<>(path));
if(startIndex >= nums.length){
return;
}
// 横向
for(int i = startIndex; i < nums.length; i++){
// 去重 “树层去重” “树枝不去重”
if(i >0 && nums[i] == nums[i-1] && used[i-1] ==false){
continue;
}
path.add(nums[i]);
used[i] = true;
// 纵向
backTracking(nums, i + 1);
used[i] = false;
path.removeLast();
}
}
}