leetcode刷題,總結,記錄,備忘300
leetcode300,Longest Increasing Subsequence
Given an unsorted array of integers, find the length of longest increasing subsequence.
For example,
Given [10, 9, 2, 5, 3, 7, 101, 18]
,
The longest increasing subsequence is [2, 3, 7, 101]
, therefore the length is 4
.
Note that there may be more than one LIS combination, it is only necessary for you to return the length.
Your algorithm should run in O(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?
Credits:
Special thanks to @pbrother for adding this problem and creating all test cases.
Subscribe to see which companies asked this question
題目提示使用動態規劃的方法去做,雖然我之前也見過一些動態規劃的題,但是並沒有去好好了解這種演算法,於是自己也去讀了很多別人的部落格,並結合這個動態規劃的入門題目,進行了一些學習。動態規劃內容我也講不清楚,自己就是理解為一個大的問題,可以分解成一個一個的小問題,然後將每個小的問題的結果快取下來,然後合成最終問題的解,其中有些規則和使用條件的什麼的,實在太抽象了,不能很好的瞭解,先擱置,以具體題目為目標,再慢慢的瞭解。言歸正傳,這個題目使用動態規劃來解,從第一個數開始,算出在每個下標上的最長遞增長度,然後取其中最大的一個即可。此時需要一個數組儲存每個下標位置上的結果,假設這個陣列為len,長度與目標陣列相同,並設其第一個元素為1。接著開始從目標陣列的第二個下標開始遍歷,巢狀的第二個迴圈從陣列頭開始,直到當前的下標,獲得當前下標為終點的序列的最大遞增長度,存放在len陣列中,一直遍歷完為止,將最大值返回。可能說起來比較抽象,看下程式碼,用實際數字試一下會更好理解。
這只是一種方法,巢狀迴圈,耗時比較多,還有一種二分法,先上第一種的程式碼。
第二種方法為二分法,耗時比較少,這種方法非常巧妙。還是需要一個另外的陣列,用來儲存元素。首先將目標陣列第一個數放入臨時的陣列,然後從第二個下標開始遍歷目標陣列,與臨時陣列中最後一個數進行比較大小,如果大的話,將元素放入臨時陣列,並且用來計算長度的變數同時增加,如果小於的話,就在該臨時陣列中使用二分的方法尋找比他小的數,放在那個數前面,如果找不到的話,就直接放在頭部,,如果有已這個數開頭的又一個遞增序列的話,如果長度比之前的長,就會覆蓋之前的數,並使計算長度的變數變的更大,最後在遍歷完目標陣列之後,這個長度變數便是最終的結果,光說還是太抽象了,還是上程式碼。自己實際操作會更有助於理解。class Solution { public: int lengthOfLIS(vector<int>& nums) { if (nums.size() == 0) { return 0; } vector<int> len(nums.size()); len[0] = 1; int maxlen = 1; for (int i = 1; i < nums.size(); ++i) { int max = 0; for (int j = 0; j < i; ++j) { if (nums[i] > nums[j] && len[j] > max) { max = len[j]; } } len[i] = max + 1; if (len[i] > maxlen) { maxlen = len[i]; } } return maxlen; } };
class Solution {
public:
int Bsearch(vector<int> len, int start, int end, int key)
{
if (start == end)
{
return key > len[start] ? start : start - 1;
}
while (start <= end)
{
int mid = (start + end) / 2;
if (key > len[mid] && key < len[mid + 1])
{
return mid;
}
else if (key < len[mid])
{
end = mid - 1;
}
else if (key > len[mid])
{
start = mid + 1;
}
else if (key == len[mid])
{
return mid - 1;
}
}
return 0;
}
int lengthOfLIS(vector<int>& nums) {
if (nums.size() == 0)
{
return 0;
}
vector<int> len(nums.size() + 1);
int maxlen = 1;
int n;
len[1] = nums[0];
for (int i = 1; i < nums.size(); ++i)
{
if (nums[i] > len[maxlen])
{
n = ++maxlen;
}
else
{
n = Bsearch(len, 1, maxlen, nums[i]) + 1;
}
len[n] = nums[i];
}
return maxlen;
}
};
兩種演算法時長相差了90ms。。。。。