题目链接:
Longest Increasing Subsequence
题目描述:
Given an unsorted array of integers, find the length of longest increasing subsequence.
For example,
Given [10, 9, 2, 5, 3, 7, 101, 18],
The longest increasing subsequence is [2, 3, 7, 101], therefore the length is 4. Note that there may be
more than one LIS combination, it is only necessary for you to return the length.
Your algorithm should run in O(n2) complexity.
题目解释:
给定一个无序的数组,找出这个数组中的最长上升子序列,例如数组[10, 9, 2, 5, 3, 7, 101, 18]中的最长上升子序列为[2, 3, 7, 101]。
这是一道比较经典的题目,在这里我们尝试利用动态规划方法来解决它。
解题方案:
动态规划的解题方式基本都会分为两步:
- 划分子问题。
- 寻找子问题之间的状态转换方程。
一个存放着N个元素的数组,我们可以划分成N-1,N-2 …i….2,1 这N种状态,然后由i-1 状态转换到第i个状态。这样一步一步的从1递推到N,就求到了结果。
我们用一个maxLen数组来存储以第i个元素为结尾的前i个元素的最小上升子序列,然后求得这N个划分中最大的个数即可。
状态转换方程可以这样写:
maxLen[k] = max(maxLen[i]) + 1
当然这里有一个前提,以元素k为结尾,那么我们在选取前k个划分中最长子序列时要保证第i个元素小于k。
下面看代码:
/*
*最长上升子序列的状态转换方程为
*maxLen[k] = nums[i] < num[k] && max(maxLen[i]);
*maxLen[k] = max + 1;
*/
int lengthOfLIS(int* nums, int numsSize)
{
if(numsSize == 1)
{
return 1;
}
int maxLen[numsSize];//记录以第i个元素为终点的最长子序列
int max_all = 0; //记录最长子序列的长度
maxLen[0] = 1;
for(int i = 1; i < numsSize; ++i)
{
int max_before = 0;//寻找前k个元素中最长上升子序列
for (int j = 0; j < i; ++j)
{
if(nums[j] < nums[i])
{
if(max_before < maxLen[j])
{
max_before = maxLen[j];
}
}
}
maxLen[i] = max_before + 1;
if(max_all < maxLen[i])//寻找全局最长的子序列
{
max_all = maxLen[i];
}
}
return max_all;
}