300. 最长上升子序列
描述:
给定一个无序的整数数组,找到其中最长上升子序列的长度。
链接:https://leetcode-cn.com/problems/longest-increasing-subsequence/
思路:
最近开始学习动态规划,拿到这个题目完全没有思路,看的题解。上面给出了两种思路动态规划和二分查找。我重点在学习动态规划,我阅读过后的理解。
动态规划是一种增量式解题策略,将一个全局的复杂问题,分解为局部的、分阶段的子问题,并且有一个特点,前一步的结果或结论可以被后一步直接利用,提高效率。
具体到本题:
状态定义:
d
p
[
i
]
dp[i]
dp[i]表示以第
i
i
i个数为结束的上升子序列长度
状态转移:在知道
[
0
,
i
)
[0, i)
[0,i)区间内状态条件下,
d
p
[
i
]
dp[i]
dp[i]可以通过遍历地比较
n
u
m
s
[
j
]
,
j
ϵ
[
0
,
i
)
nums[j], j\epsilon[0,i)
nums[j],jϵ[0,i)的数值,如果数值较大并且,则说明
n
u
m
s
[
0
:
i
]
nums[0:i]
nums[0:i]能构成长度大一位的上升子序列,此外,如果满足
d
p
[
i
]
>
d
p
[
j
]
+
1
dp[i]>dp[j]+1
dp[i]>dp[j]+1,则更新dp[i]的值,表示搜索中最新的子序列长度。其状态转移方程:
d
p
[
i
]
=
d
p
[
j
]
+
1
,
n
u
m
s
[
i
]
>
n
u
m
s
[
j
]
a
n
d
d
p
[
i
]
<
d
p
[
j
]
+
1
,
j
ϵ
[
0
,
i
)
dp[i] = dp[j]+1, nums[i]>nums[j]\ and \ dp[i]<dp[j]+1, j\epsilon[0,i)
dp[i]=dp[j]+1,nums[i]>nums[j] and dp[i]<dp[j]+1,jϵ[0,i)
int lengthOfLIS(vector<int>& nums) {
if (nums.empty())
return 0;
int length = nums.size();
vector<int> dp(length, 1);
for(auto i = 1; i < length; i++)
{
for(auto j = 0; j < i; j++) {
if (nums[i] > nums[j] && (dp[j] + 1) > dp[i]) {
dp[i] = dp[j] + 1;
}
}
}
// 找出dp数值中最大上升子序列长度
auto max_iter = max_element(dp.begin(), dp.end());
return *max_iter;
}