题目描述
给定一个无序的整数数组,找到其中最长上升子序列的长度。
示例:
输入: [10,9,2,5,3,7,101,18]
输出: 4
解释: 最长的上升子序列是 [2,3,7,101],它的长度是 4。
说明:
可能会有多种最长上升子序列的组合,你只需要输出对应的长度即可。
你算法的时间复杂度应该为 O(n2) 。
进阶: 你能将算法的时间复杂度降低到 O(n log n) 吗?
来源:力扣(LeetCode)
题解
动态规划
定义
d
p
[
i
]
dp[i]
dp[i]为以
n
u
m
s
[
i
]
nums[i]
nums[i]为最后检测元素的最长上升子序列的长度。
从小到大计算
d
p
dp
dp数组的值:
- if n u m s [ j ] < n u m s [ i ] a n d j < i , d p [ i ] = m a x ( d p [ j ] ) + 1 nums[j]<nums[i] \quad and \quad j<i,dp[i]=max(dp[j])+1 nums[j]<nums[i]andj<i,dp[i]=max(dp[j])+1
- else d p [ i ] = 1 dp[i]=1 dp[i]=1
则最大值为 m a x ( d p [ i ] ) , i = 1 , 2 , … , n max(dp[i]),i=1,2,\dots ,n max(dp[i]),i=1,2,…,n
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n=(int)nums.size();
if (n == 0) return 0;
vector<int> dp(n, 0);
for (int i = 0; i < n; ++i) {
dp[i] = 1;
for (int j = 0; j < i; ++j) {
if (nums[j] < nums[i]) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
}
return *max_element(dp.begin(), dp.end());
}
};
复杂度分析:
时间复杂度:
O
(
n
2
)
O(n^2)
O(n2)
空间复杂度:
O
(
n
)
O(n)
O(n)
贪心+二分查找
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int len = 1, n = nums.size();
if (n == 0) return 0;
vector<int> d(n + 1, 0);
d[len] = nums[0];
for (int i = 1; i < n; ++i) {
if (nums[i] > d[len]) d[++len] = nums[i];
else{
int l = 1, r = len, pos = 0; // 如果找不到说明所有的数都比 nums[i] 大,此时要更新 d[1],所以这里将 pos 设为 0
//二分查找
while (l <= r) {
int mid = (l + r) / 2;
if (d[mid] < nums[i]) {
pos = mid;
l = mid + 1;
}
else r = mid - 1;
}
d[pos + 1] = nums[i];
}
}
return len;
}
};
复杂度分析:
时间复杂度:
O
(
n
log
n
)
O(n\log n)
O(nlogn)
空间复杂度:
O
(
n
)
O(n)
O(n)