代码随想录算法训练营第28天 | 93.复原IP地址 78.子集 90.子集II

复原IP地址

代码随想录算法训练营第28天 | 93.复原IP地址 78.子集 90.子集II_第1张图片
这道题也是分割问题。但是这道题最后求的是字符串数组,所以可以直接在原字符串上插入逗点。分割的模拟不用多说,用 [startIndex, i] 来模拟分割字符段。当逗点数目达到3时就可以判断递归结束。同时还要实现一个判断字段是否有效的函数。

class Solution{
public:
	vector<string> result;
	bool isValid(string s, int start, int end){
		if(start > end)  return false;
		if(s[start] == '0' && start != end){
			return false;
		}
		string str = s.substr(start, end - start + 1);
		if(stol(str) > 255)  return false;
		return true;
	}
	void backtracking(string& s, int startIndex, int pointNums){
		if(pointNums == 3){
			if(isValid(s, startIndex, s.size() - 1)){
				result.push_back(s);
			}
			return;
		}
		for(int i = startIndex; i < s.size(); i++){
			if(isValid(s, startIndex, i)){  // 判断当前的分割字段是否有效
				s.insert(s.begin() + i + 1, '.');  //将.插入到下标i的字符后面
				backtracking(s, i + 2, pointNums + 1);  // 插入了一个逗点,所以下一层startIndex要从i+2开始
				s.erase(s.begin() + i + 1);
			}
			else  break;
		}
	}
	vector<string> restoreIpAddresses(string s){
		result.clear();
		if(s.size() < 4 && s.size() > 12)  return result;
		backtracking(s, 0, 0);
		return result;
	}
};

这个代码里坑还是挺多的,stoi函数容易有很多错误,注意 int 型范围。判断合法函数中也要加上start > end的判断,因为可能逗点添加在字符串的末尾了,导致 start(i+2)比 end 大。

子集

代码随想录算法训练营第28天 | 93.复原IP地址 78.子集 90.子集II_第2张图片
子集问题和一开始组合问题比较相似,原数组中每个元素只能使用一次。但是子集问题需要在递归过程始终记录 path,组合和分割问题只需要在遇到抽象树的叶子节点时才记录 path,因为这两种问题总会有一些条件限制作为递归终止条件。

class Solution{
public:
	vector<vector<int>> result;
	vector<int> path;
	void backtracking(vector<int>& nums, int startIndex){
		result.push_back(path);  // 在递归过程中始终记录path,子集问题的特点
		if(startIndex == nums.size()){
			return;
		}
		for(int i = startIndex; i < nums.size(); i++){
			path.push_back(nums[i]);
			backtracking(nums, i + 1);
			path.pop_back();
		}
	}
	vector<vector<int>> subsets(vector<int>& nums){
		result.clear();
		path.clear();
		backtracking(nums, 0);
		return result;
	}
};

子集II

代码随想录算法训练营第28天 | 93.复原IP地址 78.子集 90.子集II_第3张图片
这道题就是重复元素的组合问题向子集问题的迁移,在进行递归回溯前对 nums 进行排序。这里需要注意只在树层去重是不够的,排序在子集问题中是必须的,因为要始终记录 path,不排序只树层去重会在不同树层有重复情况出现。

class Solution{
public:
	vector<vector<int>> result;
	vector<int> path;
	void backtracking(vector<int>& nums, int startIndex){
		result.push_back(path);
		for(int i = startIndex; i < nums.size(); i++){
			if(i > startIndex && 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){
		result.clear();
		path.clear();
		sort(nums.begin(), nums.end());
		backtracking(nums, 0);
		return result;
	}
};

你可能感兴趣的:(算法)