题目要求:给定一个只包含数字的字符串,复原它并返回所有可能的 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 地址。
示例 1:
示例 2:
示例 3:
示例 4:
示例 5:
提示:
其实只要意识到这是切割问题,切割问题就可以使用回溯搜索法把所有可能性搜出来,和刚做过的131.分割回文串 (opens new window)就十分类似了。
- class Solution {
- public:
- vector
res; - void backtracking(string& s, int startIndex, int pointNum) {
- if (pointNum == 3) {
- if (isValid(s, startIndex, s.size() - 1)) {
- res.push_back(s);
- }
- return;
- }
- for (int i = startIndex; i < s.size(); i++) {
- if (isValid(s, startIndex, i)) {
- s.insert(s.begin() + i + 1, '.');
- pointNum++;
- backtracking(s, i + 2, pointNum);
- pointNum--;
- s.erase(s.begin() + i + 1);
- } else break;
- }
- }
- bool isValid(const string& s, int start, int end) {
- if (start > end) return false;
- if (s[start] == '0' && start != end) return false;
- int num = 0;
- for (int i = start; i <= end; i++) {
- if (s[i] > '9' || s[i] < '0') return false;
- num = num * 10 + (s[i] - '0');
- if (num > 255) return false;
- }
- return true;
- }
- vector
restoreIpAddresses(string s) { - res.clear();
- if (s.size() < 4 || s.size() > 12) return res;
- backtracking(s, 0, 0);
- return res;
- }
- };
题目要求:给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例: 输入: nums = [1,2,3] 输出: [ [3], [1], [2], [1,2,3], [1,3], [2,3], [1,2], [] ]
如果把 子集问题、组合问题、分割问题都抽象为一棵树的话,那么组合问题和分割问题都是收集树的叶子节点,而子集问题是找树的所有节点!
有同学问了,什么时候for可以从0开始呢?
求排列问题的时候,就要从0开始,因为集合是有序的,{1, 2} 和{2, 1}是两个集合,排列问题我们后续的文章就会讲到的。
以示例中nums = [1,2,3]为例把求子集抽象为树型结构,如下:
不要收集两遍(在终止条件中收集又在回溯之前收集)
- class Solution {
- public:
- vector<int> path;
- vector
int>> res; - void backtracking(const vector<int>& nums, int startIndex) {
- // 收集子集,要放在终止添加的上面,否则会漏掉自己
- res.push_back(path);
- if (startIndex >= nums.size() || path.size() == nums.size()) {
- return;
- }
- for (int i = startIndex; i < nums.size(); ++i) {
- path.push_back(nums[i]);
- backtracking(nums, i + 1);
- path.pop_back();
- }
- }
- vector
int>> subsets(vector<int>& nums) { - path.clear();
- res.clear();
- backtracking(nums, 0);
- return res;
- }
- };
题目要求:
给定一个可能包含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。
说明:解集不能包含重复的子集。
示例:
首先是排序,把一样的元素汇集在一起,然后是需要有一个Bool数组或者StartIndex来控制同一层不能有一样的元素。
- class Solution {
- public:
- vector<int> path;
- vector
int>> res; - void backtracking(const vector<int>& nums, int startIndex, vector<bool> used) {
- res.push_back(path);
- if (startIndex > nums.size() || path.size() == nums.size()) return;
- for (int i = startIndex; i < nums.size(); ++i) {
- if (i > 0 && nums[i] == nums[i-1] && used[i-1] == false) continue;
- path.push_back(nums[i]);
- used[i] = true;
- backtracking(nums, i+1, used);
- used[i] = false;
- path.pop_back();
- }
- }
-
- vector
int>> subsetsWithDup(vector<int>& nums) { - path.clear();
- res.clear();
- vector<bool> used(nums.size(), false);
- sort(nums.begin(), nums.end());
- backtracking(nums, 0, used);
- return res;
- }
- };