93. 复原 IP 地址
- 题目链接:93. 复原 IP 地址
- 解题思路:复原ip地址本质上也是切割问题,每次切割一部分加点,可以参考之前回文串分割的题。因为是ip分割,所以有一些约束,例如只能分割成四份,每份的值在0-255之间,除了0之外数字不能以0做前缀等。也可以抽象为树结构,每次切割一部分并回溯,需要维护两个用来标记位置的变量,一个startindex用于标记每次切割时的起始位置,还需要一个变量pointnum记录添加的分割点的数量,因为有四段的限制,pointnum为3时就应该直接讲剩余部分作为整体判断是否符合约束。
- 主要难点:约束条件的添加,最后一段判断后的返回逻辑
- 解题时间:30+5
- 代码:
class Solution {
List<String> res=new ArrayList<>();
public List<String> restoreIpAddresses(String s) {
if(s.length()>12){
return res;
}
back(s,0,0);
return res;
}
private void back(String s,int startIndex,int pointNum){
if(pointNum==3){
if(isVaild(s,startIndex,s.length()-1)){
res.add(s);
}
return;
}
for(int i=startIndex;i<s.length();i++){
if(isVaild(s,startIndex,i)){
s=s.substring(0,i+1)+"."+s.substring(i+1);
pointNum++;
back(s,i+2,pointNum);
pointNum--;
s=s.substring(0,i+1)+s.substring(i+2);
}else{
break;
}
}
}
private boolean isVaild(String s,int start,int end){
if(start>end){
return false;
}
if(s.charAt(start)=='0'&&start!=end){
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. 子集
- 题目链接:78. 子集
- 解题思路:本题和前面几个题都是建立树结构,不同的是之前的题是收集叶子节点,本体需要收集所有节点。在遍历时从原数组中抽取加入当前结点的序列,当原数组为空时说明到了叶子节点,则进行回溯。本题可以不用剪枝,因为本来就是需要获取所有的树节点,是一个全排列问题。
- 解题时间:25+5
- 代码:
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> subsets(int[] nums) {
back(nums,0);
return res;
}
private void back(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]);
back(nums, i + 1);
path.removeLast();
}
}
}
90. 子集 II
- 题目链接:90. 子集 II
- 解题思路:和上题类似,区别是集合里有重复元素了,并且要求返回集合不能有重复的结果,所以需要加入去重的步骤。在树结构中,从上到下一条路径上是可以加入重复元素的,但是在同一层中进行选取时不能选同样元素,可以通过维护一个used数组来标记哪些元素已经在当前层被加入。
- 主要难点:树层去重(二刷重点看)
- 解题时间:25+5
- 代码:
class Solution {
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];
subsetsWithDupHelper(nums, 0);
return result;
}
private void subsetsWithDupHelper(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]){
continue;
}
path.add(nums[i]);
used[i] = true;
subsetsWithDupHelper(nums, i + 1);
path.removeLast();
used[i] = false;
}
}
}