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?
算法一,動態規劃
O(n*n) 在leetcode上實際執行時間爲188ms
從左到右依次確定每個元素的LIS。
在確定當前元素的LIS,需要與左面的元素依次作比較:
如果左面的元素小於當前元素,則當前元素的LIS爲左面的元素LIS+1;相等,則LIS與之相等。
取其最大值爲當前元素的LIS值。
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
vector<int> lengths(nums.size(), 1);
int max_length = 0;
for (size_t i=0; i<nums.size(); ++i) {
for (int j=i-1; j>=0; --j) {
if (nums[j] < nums[i])
lengths[i] = max(lengths[i], lengths[j]+1);
else if (nums[j] == nums[i])
lengths[i] = max(lengths[i], lengths[j]);
}
max_length = max(max_length, lengths[i]);
}
return max_length;
}
};
算法二,
O(n log n),
在leetcode上執行時間爲4ms。
維持一個潛在的LIS隊列,
在隊列中進行折半查找。找到滿足>=當前值,隊列中最小元素。即左邊界。執行替換。
注意,這個隊列,並不一定是合法的LIS。
但長度一定是對的,而且最後一個元素也是對的。
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
vector<int> seq;
for (auto i: nums) {
auto iter = lower_bound(seq.begin(), seq.end(), i);
if (iter == seq.end())
seq.push_back(i);
else
*iter = i;
}
return seq.size();
}
};
算法來源:http://www.geeksforgeeks.org/longest-monotonically-increasing-subsequence-size-n-log-n/