93.复原IP地址
https://leetcode.cn/problems/restore-ip-addresses/
和前面那个回文串差不多,就是找各种方法来切割,然后判断是否合法就行。
class Solution {
public:
bool isValid(string s) {
if(s.length() > 1 && s[0] == '0') return false;
int x = stoi(s);
if (x < 0 || x > 255) return false;
return true;
}
vector<string> result;
vector<string> path;
void backTracking(string s) {
if (s.empty() && path.size() == 4) {
result.push_back(path[0] + '.' + path[1] + '.' + path[2] + '.' + path[3]);
return;
}
if (s.empty()) return;
if (path.size() == 4) return;
for (int i = 0; i < (s.length() < 3 ? s.length() : 3); i++) {
string left(s.begin(), s.begin() + i + 1);
if (!isValid(left)) continue;
path.push_back(left);
string right(s.begin() + i + 1, s.end());
backTracking(right);
path.pop_back();
}
}
vector<string> restoreIpAddresses(string s) {
backTracking(s);
return result;
}
};
78.子集
https://leetcode.cn/problems/subsets/
这道题我一开始想的很复杂
思路是这样的,先限定一个path大小的值k,回溯得到大小为k的所有子集添加到result中,然后依次从k=0到k=nums.size()全部回溯一遍
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backTracking(vector<int> nums, int k) {
//k : 还需要再path中添加的元素数量
if (k == 0) {
result.push_back(path);
return;
}
if (nums.empty()) {
return;
}
for (int i = 0; i < nums.size(); i++) {
//i : 添加到path中的元素位置
path.push_back(nums[i]);
vector<int> nums2(nums.begin() + i + 1, nums.end());
backTracking(nums2, k - 1);
path.pop_back();
}
}
vector<vector<int>> subsets(vector<int>& nums) {
for (int i = 0; i <= nums.size(); i++) {
backTracking(nums, i);
}
return result;
}
};
后面发现其实就正常的回溯,只不过收集的条件从path大小达到要求改为每一步都收集……
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backTracking(vector<int> nums, int cur) {
result.push_back(path);
for(int i = cur; i < nums.size(); i++){
path.push_back(nums[i]);
backTracking(nums, i + 1);
path.pop_back();
}
}
vector<vector<int>> subsets(vector<int>& nums) {
backTracking(nums, 0);
return result;
}
};
直接操作数组:
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backTracking(vector<int>& nums) {
result.push_back(path);
if (nums.empty()) return;
for(int i = 0; i < nums.size(); i++){
path.push_back(nums[i]);
vector<int> nums2(nums.begin() + i + 1, nums.end());
backTracking(nums2);
path.pop_back();
}
}
vector<vector<int>> subsets(vector<int>& nums) {
backTracking(nums);
return result;
}
};
90.子集II
https://leetcode.cn/problems/subsets-ii/
和上面的子集问题差不多,但是多了一个去重的需求
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backTracking(vector<int> nums, int cur) {
result.push_back(path);
if (cur >= nums.size()) return;
for(int i = cur; i < nums.size(); i++) {
if (i > cur && nums[i] == nums[i - 1]) continue;
path.push_back(nums[i]);
backTracking(nums, i + 1);
path.pop_back();
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
backTracking(nums, 0);
return result;
}
};
直接操作数组:
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backTracking(vector<int> nums) {
result.push_back(path);
if (nums.empty()) return;
for(int i = 0; i < nums.size(); i++){
if (i > 0 && nums[i] == nums[i - 1]) continue;
path.push_back(nums[i]);
vector<int> nums2(nums.begin() + i + 1, nums.end());
backTracking(nums2);
path.pop_back();
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
backTracking(nums);
return result;
}
};
使用set去重:
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
void backTracking(vector<int> nums, int cur) {
result.push_back(path);
if (cur >= nums.size()) return;
unordered_set<int> set;
for(int i = cur; i < nums.size(); i++) {
if (!set.empty() && set.find(nums[i]) != set.end()) continue;
set.insert(nums[i]);
path.push_back(nums[i]);
backTracking(nums, i + 1);
path.pop_back();
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
vector<bool> used(nums.size(), false);
sort(nums.begin(), nums.end());
backTracking(nums, 0);
return result;
}
};
使用used去重:
class Solution {
public:
vector<vector<int>> result;
vector<int> path;
vector<bool> used = {false};
void backTracking(vector<int> nums, int cur) {
result.push_back(path);
if (cur >= nums.size()) return;
for(int i = cur; i < nums.size(); i++) {
if (i >= 1 && nums[i] == nums[i-1] && used[i-1] == false) continue;
path.push_back(nums[i]);
used[i] = true;
backTracking(nums, i + 1);
path.pop_back();
used[i] = false;
}
}
vector<vector<int>> subsetsWithDup(vector<int>& nums) {
sort(nums.begin(), nums.end());
backTracking(nums, 0);
return result;
}
};