93.复原IP地址 ⭐️
- 链接:代码随想录
本题还是分割问题
难的在于字符串的处理
-
解题思路:
①要处理的字符串是不断修改的,难点在于修改的过程
②本题不同之处,终止条件改为加点个数,而不是和切割字符串一样完整的分割字符串
③是否有效处理:涉及到三个方面的检查 -
图像理解
public class Solution {
private List<String> res = new ArrayList<>();
public List<String> restoreIpAddresses(String s) {
//剪枝
if(s.length() > 12){
return res;
}
backtracking(s,0,0);
return res;
}
/**
*
* @param s 处理的字符串
* @param startIndex 每一层的分割位置
* @param pointSum 表示加点的个数
*/
private void backtracking(String s, int startIndex, int pointSum) {
if(pointSum == 3){
//判断最后一个点到最后有效
if(isStringValid(s, startIndex, s.length() - 1)){
res.add(new String(s));
return;
}
}
//处理逻辑
for (int i = startIndex; i < s.length(); i++) {
//判断是否满足加入条件
if(isStringValid(s, startIndex, i)){
s = s.substring(0, i + 1) + "." + s.substring(i + 1);
pointSum++;
//i + 1的位置.已经占了
backtracking(s, i + 2, pointSum);
//回溯
pointSum--;
s = s.substring(0, i + 1) + s.substring(i + 2);
}else{
//进行剪枝操作
break;
}
}
}
//[start,end]
private boolean isStringValid(String s,int start,int end){
if(start > end){
return false;
}
if(s.charAt(start) == '0' && start != end){//排除0开头
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){
return false;
}
}
return true;
}
}
78.子集
题目链接:代码随想录
本题为搜集子集问题,与之前的组合问题不同,本题需要搜集树上的所有节点,因此也不需要剪枝
那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!
-
解题思路:
①参数:要传入要找子集的数组和防止重复选取的startIndex
②终止条件:就是startIndex已经大于数组的长度了,就终止了,因为没有元素可取了
③单层逻辑: 每一次加上nums[i],表示本层选取的元素,再深入下一层取元素
④收集元素:该树上的每个节点都要收集,因此每一层刚开始要收集本层元素 -
图像理解
public class Solution1 {
private List<List<Integer>> res = new ArrayList<List<Integer>>();
private List<Integer> path = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
backtracking(nums,0);
return res;
}
private 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
本题解法:子集问题 + 去重
题目链接:代码随想录
-
解题思路:
①startIndex防止重复使用数组中某一元素
②used数组进行树枝去重 -
图像理解:
public class Solution2 {
private List<List<Integer>> res = new ArrayList<List<Integer>>();
private 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;
}
private void backtracking(int[] nums,int startIndex,int[] used){
//把每一层收集到的元素添加到结果集中
res.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] == 0){
continue;//跳过这一分支
}
used[i] = 1;//当前元素使用过了
path.add(nums[i]);
backtracking(nums, i + 1, used);//i + 1防止重复使用数组中某一元素
//回溯
used[i] = 0;
path.remove(path.size() - 1);
}
}
}