給定乙個無序的整數陣列,找到其中最長上公升子串行的長度。
示例:
輸入: [10,9,2,5,3,7,101,18]本來想暴力解決一下,思路是從頭到尾選取子串行的開始元素,然後固定開始元素後,向後遍歷,只要後乙個比前乙個元素大,長度就加1輸出: 4
解釋: 最長的上公升子串行是 [2,3,7,101],它的長度是 4。
後來發現,這樣是不對的,假如開始元素選擇了2
,按我的思路,下一步就直接選擇5
做為後繼元素了,這樣得到的結果是[2, 5, 7, 101]
,額。。。好吧,雖然和答案得到的長度一樣,但是如果陣列為[10,9,2,5,3,4,7,101,18]
的話,我的思路得到的是[2,5,7,101]
,但是答案卻是[2,3,4,7,101]
,因此這種暴力方法是錯誤的
看來,解決子串行問題還是需要動態規劃
方法一:動態規劃
動態規劃最核心的思想就是避免重複操作
狀態定義:dp[i]
表示陣列前i個數字,且以第i
個數字結尾的最長上公升子串行的長度
狀態轉移:dp[i] = max(dp[j]) + 1
,其中0 <= j < i 且 nums[j] < nums[i]
初始狀態:dp[i]
所有元素置為1,含義是每個元素都至少可以單獨成為子串行,此時長度都為 1
返回值:dp
列表最大值,即可得到全域性最長上公升子串行長度
class
solution
};
方法二:貪心+二分查詢
考慮乙個簡單的貪心,如果我們要使上公升子串行盡可能的長,則我們需要讓序列上公升得盡可能慢,因此我們希望每次在上公升子串行最後加上的那個數盡可能的小。
基於上面的貪心思路,我們維護乙個陣列d[i]
,表示長度為i
的最長上公升子串行的末尾元素的最小值,用len
記錄目前最長上公升子串行的長度,起始時len
為1
,d1=nums[0]
同時我們可以注意到d[i]
是關於i
單調遞增的。因為如果d[j]>= d[i]
且j < i
,我們考慮從長度為i
的最長上公升子串行的末尾刪除i-j
個元素,那麼這個序列長度變為j
,且第j
個元素x(末尾元素)必然小於d[i]
,也就小於d[j]
。那麼我們就找到了乙個長度為j
的最長上公升子串行,並且末尾元素比d[j]
小,從而產生了矛盾。因此陣列d
的單調性得證。
我們依次遍歷陣列nums
中的每個元素,並更新陣列d
和len
的值。如果nums[i]>d[len]
則更新len=len+1
,否則在d[1…len]
中找滿足d[i−1]根據d
陣列的單調性,我們可以使用二分查詢尋找下標i
,優化時間複雜度。
最後整個演算法流程為:
設當前已求出的最長上公升子串行的長度為len
(初始時為1
),從前往後遍歷陣列nums
,在遍歷到nums[i]
時:
以輸入序列[0, 8, 4, 12, 2]
為例:
最終得到最大遞增子串行長度為3
class
solution
vector<
int>
d(n +1,
0); d[len]
= nums[0]
;for
(int i =
1; i < n;
++i)
else
else
} d[pos +1]
= nums[i];}
}return len;}}
;
LeetCode 300 最長遞增子串行
300.最長遞增子串行 我們記狀態 dp i dp i dp i 表示以第 i ii 個元素結尾的最長上公升子串行的長度,那麼專一方程就可以定義為 dp i m ax d p j 1 0 j ndnu ms j ms i dp i max dp j 1 0 leq jdp i max dp j 1 ...
LeetCode300 最長遞增子串行
題目鏈結 題目描述 給你乙個整數陣列 nums 找到其中最長嚴格遞增子串行的長度。子串行是由陣列派生而來的序列,刪除 或不刪除 陣列中的元素而不改變其餘元素的順序。例如,3,6,2,7 是陣列 0,3,1,6,2,2,7 的子串行。示例 輸入 nums 10,9,2,5,3,7,101,18 輸出 ...
leetcode 300 最長遞增子串行
思路,動態規劃 狀態含義 dp i 第i個元素所表示的最大的遞增序列長度 轉移方程 第i個是否可以放在第j個後面 1.可以放,dp i max dp i dp j 1 2.不可以放,跳過 遍歷dp找最大 class solution max max max,dp i return max inclu...