leetcode 93. 复原 IP 地址
题目描述
有效 IP 地址 正好由四个整数(每个整数位于 0 到 255 之间组成,且不能含有前导 0),整数之间用 '.' 分隔。
- 例如:
"0.1.2.201"和"192.168.1.1"是 有效 IP 地址,但是"0.011.255.245"、"192.168.1.312"和"192.168@1.1"是 无效 IP 地址。
给定一个只包含数字的字符串 s ,用以表示一个 IP 地址,返回所有可能的有效 IP 地址,这些地址可以通过在 s 中插入 '.' 来形成。你 不能 重新排序或删除 s 中的任何数字。你可以按 任何 顺序返回答案。
示例
输入:s = "101023"
输出:["1.0.10.23","1.0.102.3","10.1.0.23","10.10.2.3","101.0.2.3"]
题目链接
https://leetcode.cn/problems/restore-ip-addresses/
解题思路
核心是将三个 .放在哪儿?
- 不能有前导
0 - 整数位于
0到255之间
用 pointNum记录已插入 .的数量,index记录当前截断字符串的起始下标。那么只有当 index == s.length()和 pointNum == 4同时满足时,才是将整个字符串分割完成,即一次有效分割,添加结果到结果集合。其余情况均为无效分割。
同时只有当 pointNum < 3时,才在当前路径后添加 .
剪枝情况:
i - index < 3每一段ip至多不超过3个字符i > index && s.charAt(index) == '0'去除前导0Integer.parseInt(s.substring(index, i + 1)) > 255去除大于255的情况,由于题目明确s只包含数字,所以满足上述情况,其数值一定大于0,不用再做这部分剪枝
另一个关键点,使用 lenBefore记录当前情况的长度,之后使用 setLength(lenBefore)进行回溯删除。
class Solution {
List<String> ans = new ArrayList<>();
StringBuilder sb = new StringBuilder();
public List<String> restoreIpAddresses(String s) {
traceBack(s, 0, 0);
return ans;
}
public void traceBack(String s, int index, int pointNum) {
if (index == s.length() && pointNum == 4) {
ans.add(sb.toString());
return;
}
if (index == s.length() || pointNum == 4) return;
for (int i = index; i < s.length() && i - index < 3; i++) {
if (s.charAt(index) == '0' && i > index) break;
int num = Integer.parseInt(s.substring(index, i + 1));
if (num > 255) break;
int lenBefore = sb.length(); // 记录长度
sb.append(s, index, i + 1);
if (pointNum < 3) sb.append('.');
traceBack(s, i + 1, pointNum + 1);
sb.setLength(lenBefore); // 回溯删除
}
}
}
leetcode 78. 子集
题目描述
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。
示例
输入:nums = [1,2,3]
输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]
题目链接
https://leetcode.cn/problems/subsets
解题思路
在每次访问中记录当前的访问情况。终止状态可以不用写。
class Solution {
List<List<Integer>> ans = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> subsets(int[] nums) {
traceBack(nums, 0);
return ans;
}
public void traceBack(int[] nums, int index) {
ans.add(new ArrayList<>(path));
/*
if (index == nums.length) {
return;
}
*/
for (int i = index; i < nums.length; i++) {
path.add(nums[i]);
traceBack(nums, i + 1);
path.removeLast();
}
}
}
leetcode 90. 子集 II
题目描述
给你一个整数数组 nums ,其中可能包含重复元素,请你返回该数组所有可能的 子集(幂集)。
解集 不能 包含重复的子集。返回的解集中,子集可以按 任意顺序 排列。
示例
输入:nums = [1,2,2]
输出:[[],[1],[1,2],[1,2,2],[2],[2,2]]
题目链接
https://leetcode.cn/problems/subsets-ii
解题思路
和上一题一样,不同的是,需要先对数组排序,然后使用 i > index && nums[i] == nums[i - 1]剪枝
class Solution {
List<List<Integer>> ans = new ArrayList<>();
List<Integer> path = new ArrayList<>();
public List<List<Integer>> subsetsWithDup(int[] nums) {
Arrays.sort(nums);
traceBack(nums, 0);
return ans;
}
public void traceBack(int[] nums, int index) {
ans.add(new ArrayList<>(path));
if (index == nums.length) {
return;
}
for (int i = index; i < nums.length; i++) {
// i > index, 不是i > 0。只有用过了,才能筛,而不是从头开始
if (i > index && nums[i] == nums[i - 1]){
continue;
}
path.add(nums[i]);
traceBack(nums, i + 1);
path.removeLast();
}
}
}
评论