1 题目分析
给定一个无序数组,求解其最长上升子序列.
https://leetcode-cn.com/problems/longest-increasing-subsequence/
2 算法思想
2.1 动态规划算法的核心思想
动态规划算法和分治法*的核心区别是:动态规划算法划分的子问题往往不是相互独立的,若采用分治法,则需要分解很多个子问题,导致效率的下降.
动态规划算法:一般建立一个表来记录所有已经求解的子问题的答案,在需要求解下一问题的时候,就直接调用之前已经求解好答案.
2.2 结合本题目使用动态规划算法
2.2.1 问题分析
1.建立问题求解表,这道题给出了一个无序数组,大小为numsSize,所以需要建立一个大小为numsSize的表来存储对应的最长子序列的长度,这个表可以利用数组
d
p
dp
dp的形式实现.
2.由于最初状态每个元素的最长上升子序列都仅仅包含自身,故数组中所有元素的初始值为1.
3.我们需要返回这个数组中的最大值,保存数组里面的最大数字(这个最大数字就是最长子序列的长度).
4.如何遍历给出的数组:我们需要对给出数组中的每个元素确定其最长上升子序列的值,并将这个值填入我们设计的表中.所以我们需要在第一次遍历的时候,访问给出数组中的元素,并访问给出数组该元素之前的所有元素,去寻找这个元素的子序列的位置.因此,我们需要两次遍历这个给出数组.
5.如何确定数组最长子序列的长度:对于我们正在访问的元素i,如果能在
i
i
i之前的所有元素中找到一个元素
j
j
j,能够满足:
i
i
i对应的值大于
j
j
j对应的值,并且
d
p
[
i
]
<
d
p
[
j
]
+
1
dp[i] < dp[j] + 1
dp[i]<dp[j]+1,即满足并
i
i
i之后,这个子序列的长度更长.这样我们就找到
i
i
i的最长子序列长度
2.2.2 变量设置
dp[maxSize]:用来存储最长子序列的值.
i,j:用来遍历初始数组的标识值
max:记录最终结果
3 算法实现
int lengthOfLIS(int* nums, int numsSize)
{
if(numsSize == 0) return 0;
int dp[numsSize];
int i, j, max = 1;
// 2.2.1-1
for(i=0; i<numsSize; i++)
{
dp[i]=1;
}
// 2.2.1-4\5
for(i=1; i<numsSize; i++)
{
for(j=0; j<i; j++)
{
if(nums[i]>nums[j] && dp[i]<dp[j]+1)
{
dp[i] = dp[j]+1;
if(dp[i] > max)
{
max = dp[i];
}
}
}
}
return max;
}