子序列組合拳 => 最長連續子序列(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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章