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();
}
};