93. 复原 IP 地址
第一想法:使用分割法来写,但是需要考虑比较多的限制条件
难点总结:判断ip子串需要明确3种限制条件(详见代码注释)
class Solution {
List<String> res = new ArrayList<>();
StringBuilder sb = new StringBuilder();
int splitNum = 0;
public List<String> restoreIpAddresses(String s) {
backTrack(s, 0);
return res;
}
public void backTrack(String s, int startIndex) {
if (splitNum == 3) {
// 处理最后一段数字
if (isIp(s, startIndex, s.length())) {
String str = s.substring(startIndex, s.length());
sb.append(str);
res.add(sb.toString());
// 回溯需要把最后一段删掉
sb.delete(sb.length() - str.length(), sb.length());
}
return;
}
for (int i = startIndex; i < s.length(); i++) {
if (isIp(s, startIndex, i + 1)) {
String str = s.substring(startIndex, i + 1);
// 先插入子串,后插入逗号(最后一段就不需要处理逗号了)
sb.append(str);
sb.append(".");
splitNum++;
backTrack(s, i + 1);
splitNum--;
sb.deleteCharAt(sb.length() - 1);
sb.delete(sb.length() - str.length(), sb.length());
}
}
}
public boolean isIp(String s, int start, int end) {
String str = s.substring(start, end);
// 1. 如果有2-3位数,最左边数字不能为0
if (str.length() > 1 && s.charAt(start) == '0') return false;
// 2. 不能大于3位数或者小于1位数
if (str.length() <= 0 || str.length() > 3) return false;
int num = Integer.parseInt(str);
// 3. 0 <= num <= 255
if (num >= 0 && num <= 255) return true;
else return false;
}
}
用时收获:对限制条件思考较久,用时40min
- 子集
第一想法:和组合题目很相似,即:把path加入res语句放到每次回溯的开头执行
难点总结:需要体会一下组合和子集的关系
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> subsets(int[] nums) {
backtrack(nums, 0);
return res;
}
private void backtrack(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]);
backtrack(nums, i + 1);
// 要使用removeList必须得是链表
path.removeLast();
}
}
}
用时收获:用时20min
90.子集II
第一想法:理解了子集之后,本题和40. 组合总和 II类似
难点总结:横减纵不剪(如注释)
class Solution {
List<List<Integer>> res = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
backTrack(nums, 0);
return res;
}
private void backTrack(int[] nums, int startIndex) {
res.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]);
backTrack(nums, i + 1);
path.removeLast();
}
}
}
用时收获:用时12min