300. Longest Increasing Subsequence**
https://leetcode.com/problems/longest-increasing-subsequence/
題目描述
Given an unsorted array of integers, find the length of longest increasing subsequence.
Example:
Input: [10,9,2,5,3,7,101,18]
Output: 4
Explanation: The longest increasing subsequence is [2,3,7,101], therefore the length is 4.
Note:
- There may be more than one LIS combination, it is only necessary for you to return the length.
- Your algorithm should run in complexity.
Follow up: Could you improve it to time complexity?
C++ 實現 1
動態規劃.
使用 f[i]
表示以 nums[i]
結尾的 LIS. 那麼:
f[i] = max(nums[i] > nums[k] ? (f[k] + 1) : 1, f[i]); 其中 k = 1, 2, ..., i - 1
上面意思就是說, nums[i]
要和它之前的所有數字 nums[k]
進行比較, 從而找到 LIS.
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
if (nums.empty()) return 0;
int res = 1;
vector<int> f(nums.size(), 1);
for (int i = 1; i < nums.size(); ++ i) {
for (int j = i - 1; j >= 0; -- j) {
auto tmp = nums[i] > nums[j] ? f[j] + 1 : 1;
f[i] = std::max(f[i], tmp);
}
res = std::max(f[i], res);
}
return res;
}
};
C++ 實現 2
思路和 C++ 實現 1
一致, 寫法稍不同.
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
if (nums.empty()) return 0;
int n = nums.size();
vector<int> dp(n, 1);
for (int i = 1; i < n; ++i) {
for (int k = i - 1; k >= 0; k--)
if (nums[k] < nums[i])
dp[i] = (dp[k] + 1) > dp[i] ? (dp[k] + 1) : dp[i];
}
return *max_element(dp.begin(), dp.end());
}
};
C++ 實現 3
Follow Up 中要求的 方法. 相當於是將 LIS 給找出來了, 使用 res
存儲 LIS, 對於放在 LIS 中的每個元素, 如果我們訪問到 nums[i]
時, 發現 res
中有比 nums[i]
更大(或等於) 的元素, 就替換該元素. 這裏不用 upper_bound
, 否則最後出來的 LIS 就會有重複元素, 不符合 LIS 的定義.
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
if (nums.empty()) return 0;
vector<int> res;
int n = nums.size();
for (int i = 0; i < n; ++i) {
if (res.empty() || nums[i] > res.back())
res.push_back(nums[i]);
else if (nums[i] < res.back()) {
// lower_bound 是 res 中第一個大於或等於 nums[i] 的元素
auto iter = std::lower_bound(res.begin(), res.end(), nums[i]);
*iter = nums[i];
}
}
return res.size();
}
};