子序列组合拳 => 最长连续子序列(leetcode128)&最长递增子序列长度(leetcode300)&最长递增子序列个数(leetcode673)---C++实现

最长连续子序列
在这里插入图片描述
思路

1.空间换时间,利用哈希表存储原始数据。
2.遍历原始数组,例如遍历到nums[i],在哈希表中先往num[i]右边找,即num[i] + 1方向;再往左边找,即nums[i] - 1方向。
3.优化,每次往左右找时,即可把左右的数在哈希表中删除,防止重复查找 O(n)+O(n)

int longestConsecutive(vector<int>& nums) {
	if (nums.size() < 2)
		return nums.size();
	unordered_set<int>hashSet;
	for (int i = 0; i < nums.size(); i++)
		hashSet.insert(nums[i]);
	int maxConSeqLen = 0;
	for (int i = 0; i < nums.size(); i++) {
		//哈希表中存在该key则删除 且返回1;否则直接返回0 可以省去find操作 
		if (hashSet.erase(nums[i])) {
			int num = nums[i];
			int curLen = 1;
			//往右找
			while (hashSet.erase(++num))
				curLen++;
			//往左找
			num = nums[i];		//该步骤是因为num发生了改变 必须变回nums[i]
			while (hashSet.erase(--num))
				curLen++;
			maxConSeqLen = (maxConSeqLen > curLen ? maxConSeqLen : curLen);
		}
	}
	return maxConSeqLen;
}

最长递增子序列个数(包含最长递增子序列长度)
在这里插入图片描述
思路:
1.用len数组记录以每个元素为结尾的最长递增子序列长度,例如{1,3,5,4,1}对应的len数组为{1,2,2,3,1},这样最长递增子序列得解。
2.在1的基础上加上一个combination数组,记录达到当前最长递增子序列所有的子序列个数

int findNumberOfLIS(vector<int>& nums) {
	if (nums.size() < 2)
		return nums.size();
	vector<int>len(nums.size(), 1); //记录每个位置结尾的递增子序列长度
	vector<int>combination(nums.size(), 1); //记录每个位置达到该位置最长递增子序列所有的组合数
	int maxLen = 0; //记录最大递增子序列长度
	for (int i = 1; i < nums.size(); i++) {
		for (int j = 0; j < i; j++) {
			if (nums[j] < nums[i]) {
				if (len[j] == len[i])     //关键步骤
					combination[i] = combination[j];
				if (len[j] + 1 == len[i])   //关键步骤   又是一种达到最长子序列的可能
					combination[i] += combination[j];
                len[i] = max(len[i], len[j] + 1);
			}
		}
		maxLen = (maxLen > len[i] ? maxLen : len[i]);
	}
	int res = 0;
	for (int i = 0; i < nums.size(); i++) {
		if (maxLen == len[i])
			res += combination[i];
	}
	return res;
}

猜你喜欢

转载自blog.csdn.net/qq_42673507/article/details/90736745
今日推荐