您现在的位置是:首页 >技术教程 >代码随想录算法训练营第二十九天|491.递增子序列 46.全排列 47.全排列 II网站首页技术教程

代码随想录算法训练营第二十九天|491.递增子序列 46.全排列 47.全排列 II

禹泽. 2024-06-17 10:48:36
简介代码随想录算法训练营第二十九天|491.递增子序列 46.全排列 47.全排列 II

目录

LeeCode 491.递增子序列 

LeeCode 46.全排列

LeeCode 47.全排列 II 


LeeCode 491.递增子序列 

491. 递增子序列 - 力扣(LeetCode)

思路:以[4, 7, 6, 7]为例,抽象为树形结构如图:

由图可知,同一父节点下的同层上使用过的元素不能再次使用。

unordered_set<int> uset; 是记录本层元素是否重复使用,新的一层uset都会重新定义。

class Solution {
private:
    vector<vector<int>> result;
	vector<int> path;
	void backtracking(vector<int>& nums, int startIndex) {
		if (path.size() > 1) result.push_back(path);
		unordered_set<int> uset; //使用set对本层元素去重
		for (int i = startIndex; i < nums.size(); i++) {
			if ((!path.empty() && nums[i] < path.back()) 
			       || uset.find(nums[i]) != uset.end())  {
			  continue;
			}
			uset.insert(nums[i]);
			path.push_back(nums[i]);
			backtracking(nums, i + 1);
			path.pop_back();
		} 
	} 
public:
    vector<vector<int>> findSubsequences(vector<int>& nums) {
    	result.clear();
    	path.clear();
    	backtracking(nums, 0);
    	return result;
    }
};

使用数组做哈希进行优化:

class Solution {
private:
    vector<vector<int>> result;
	vector<int> path;
	void backtracking(vector<int>& nums, int startIndex) {
		if (path.size() > 1) result.push_back(path);
		int used[201] = {0}; //使用set对本层元素去重
		for (int i = startIndex; i < nums.size(); i++) {
			if ((!path.empty() && nums[i] < path.back()) 
			       || used[nums[i] + 100] == 1)  {
			  continue;
			}
			used[nums[i] + 100] = 1;
			path.push_back(nums[i]);
			backtracking(nums, i + 1);
			path.pop_back();
		} 
	} 
public:
    vector<vector<int>> findSubsequences(vector<int>& nums) {
    	result.clear();
    	path.clear();
    	backtracking(nums, 0);
    	return result;
    }
};

LeeCode 46.全排列

46. 全排列 - 力扣(LeetCode)

思路:以[1,2,3]为例,抽象成树形结构如下:

排列问题需要一个used数组,标记已选择的元素。

class Solution {
public:
	vector<vector<int>> result;
	vector<int> path;
	void backtracking(vector<int>& nums, vector<bool>& used) {
		if (path.size() == nums.size()) {
			result.push_back(path);
			return;
		}
		for (int i = 0; i < nums.size(); i++) {
			if (used[i] == true) continue;
			used[i] = true;
			path.push_back(nums[i]);
			backtracking(nums, used);
			path.pop_back();
			used[i] = false;
		}
	}
    vector<vector<int>> permute(vector<int>& nums) {
    	result.clear();
	    path.clear();
	    vector<bool> used(nums.size(), false);
	    backtracking(nums, used);
	    return result;
	}
};

LeeCode 47.全排列 II 

47. 全排列 II - 力扣(LeetCode)

思路:本题与上题区别在于出现重复元素,需要进行去重操作。

class Solution {
private:
	vector<vector<int>> result;
	vector<int> path;
	void backtracking(vector<int>& nums, vector<bool>& used) {
		if (path.size() == nums.size()) {
			result.push_back(path);
			return;
		}
		for (int i = 0; i < nums.size(); i++) {
			if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) continue;
			if (used[i] == false) {
				used[i] = true;
				path.push_back(nums[i]);
				backtracking(nums, used);
				path.pop_back();
				used[i] = false;
			}
		}
	}
public:
    vector<vector<int>> permuteUnique(vector<int>& nums) {
    	result.clear();
    	path.clear();
    	sort(nums.begin(), nums.end());
    	vector<bool> used(nums.size(), false);
    	backtracking(nums, used);
    	return result;
    }
};
风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。