题目:
93.复原IP地址
78.子集
90.子集II
学习内容:
93.复原IP地址
这道题其实就是切割问题,还是按照我们之前的模板来解决:
class Solution {
List<String> result = new ArrayList<>();
public List<String> restoreIpAddresses(String s) {
backtracking(s, 0, 0);
return result;
}
public void backtracking(String s, int startIndex, int pointNum) {
// 确定终止条件,有三个点就分隔
if (pointNum == 3) {
if (isVaild(s, startIndex, s.length() - 1)) {
result.add(s); // 判断第四段字符是否合法,合法就add进result
}
return;
}
// 搜索
for (int i = startIndex; i < s.length(); i++) {
// 判断字符是否合法,合法才能递归和回溯
if (isVaild(s, startIndex, i)) {
pointNum++;
s = s.substring(0, i + 1) + '.' + s.substring(i + 1);
backtracking(s, i + 2, pointNum); // i + 2是因为加了"."
s = s.substring(0, i + 1) + s.substring(i + 2); // 回溯还原
pointNum--;
} else {
break;
}
}
}
public boolean isVaild(String s, int start, int end) {
if (start > end) {
return false;
}
// 检查是否有前导0,注意如果是单个0是合法的
if (s.charAt(start) == '0' && start != end) {
return false;
}
int num = 0;
for (int i = start; i <= end; i++) {
// 检查是否为数字
if (!Character.isDigit(s.charAt(i))) {
return false;
}
num = num * 10 + (s.charAt(i) - '0');
if (num > 255) return false; // 注意这个判断必须写在for里面,因为必须每次循环判断一次
}
return true;
}
}
78.子集
子集问题和组合问题、分割问题的的区别,子集是收集树形结构中树的所有节点的结果。 这意味着,代码中不是在终止条件里才收集结果,而是每次for循环都要收集结果。
class Solution {
List<Integer> path = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
backtracking(nums, 0);
return result;
}
public void backtracking(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]);
backtracking(nums, i + 1);
path.removeLast();
}
}
}
90.子集II
这道题的难点就在于去重操作。实际上和前面的一样,都是树层去重,重点就是要去掉同一层用过的、相同的元素,这就需要我们提前排序,这样才能保证相同值的元素相邻。同时注意,这是子集问题,和组合与分割问题不同,要保存所有节点的结果。
class Solution {
List<Integer> path = new ArrayList<>();
List<List<Integer>> result = new ArrayList<>();
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums); // 排序
backtracking(nums, 0);
return result;
}
public 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 > startIndex && nums[i] == nums[i - 1]) {
continue;
}
path.add(nums[i]);
backtracking(nums, i + 1);
path.removeLast();
}
}
}
学习时间:
2024.4.5