一、93.复原IP地址
题目链接:https://leetcode.cn/problems/restore-ip-addresses/
文章讲解:https://programmercarl.com/0093.%E5%A4%8D%E5%8E%9FIP%E5%9C%B0%E5%9D%80.html
视频讲解:https://www.bilibili.com/video/BV1fA4y1o715
1.1 初见思路
- 思路也不难,按个数来将数字进行分组,然后判断分出来的IP是否合法
- 递归终止条件是什么?这个需要想明白
- IP地址有两个限制:1-单个不能超过255 2-总共只有4段
- 判断IP段是否合法的内部函数应该怎么实现?
1.2 具体实现
class Solution {
List<String> result = new ArrayList<>();
String tempStr = "";
public List<String> restoreIpAddresses(String s) {
backtracing(s,0,0);
return result;
}
public void backtracing(String str,int startIndex,int pointNum){
if(pointNum==3){
if(isValid(str,startIndex,str.length()-1)){
tempStr+=str.substring(startIndex,str.length());
result.add(tempStr);
tempStr = tempStr.substring(0,startIndex);
}
return;
}
for(int i=startIndex;i<str.length();i++){
if(isValid(str,startIndex,i)){
String t1=tempStr;
tempStr+=str.substring(startIndex,i+1)+".";
pointNum++;
backtracing(str,i+1,pointNum);
pointNum--;
tempStr = t1;
}
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开头的数字不合法
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;
}
}
1.3 重难点
- 使用变量pointNum,记录添加逗点的数量,来作为判断递归终止条件
二、78.子集
题目链接:https://leetcode.cn/problems/subsets/
文章讲解:https://programmercarl.com/0078.%E5%AD%90%E9%9B%86.html
视频讲解:https://www.bilibili.com/video/BV1U84y1q7Ci
2.1 初见思路
- 常规递归题目
2.2 具体实现
`class Solution {
List<List> result = new ArrayList<>();// 存放符合条件结果的集合
LinkedList 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);
path.removeLast();
}
}
}`## 2.3 重难点
- 这里path 使用LinkedList类,原因是这里频繁需要进行删除链表的最后一个元素,如果使用ArrayList的话,肯定效率没有LinkedList高,ArrayList底层是数组,查询快,LinkedList底层是链表,增删快;
三、 90.子集II
题目链接:https://leetcode.cn/problems/subsets-ii/
文章讲解:https://programmercarl.com/0090.%E5%AD%90%E9%9B%86II.htm
视频讲解:https://www.bilibili.com/video/BV1vm4y1F71J/
3.1 初见思路
- 包含重复元素,把原数组排序后,然后使用startIndex来控制
- 排序后,相同的元素不重复处理
3.2 具体实现
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
subsetsWithDupHelper(nums, 0);
return res;
}
private void subsetsWithDupHelper(int[] nums, int start) {
res.add(new ArrayList<>(path));
for (int i = start; i < nums.length; i++) {
// 跳过当前树层使用过的、相同的元素
if (i > start && nums[i - 1] == nums[i]) {
continue;
}
path.add(nums[i]);
subsetsWithDupHelper(nums, i + 1);
path.removeLast();
}
}
}