最長連續子序列
思路
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;
}