最长递增子序列
2016-05-10 20:56
417 查看
题目
给定一个整数序列arr,长度为N,找到最长上升子序列(LIS),返回LIS的长度。说明
最长上升子序列的定义:
最长上升子序列问题是在一个无序的给定序列中找到一个尽可能长的由低到高排列的子序列,这种子序列不一定是连续的或者唯一的。
样例
给出
[5,4,1,2,3],LIS 是
[1,2,3],返回
3
给出
[4,2,4,5,3,7],LIS 是
[4,4,5,7],返回
4
分析
本题也是一个动态规划算法的典型应用。需要维护一个长度为N的数组dp;dp[i]代表在以arr[i]这个数 为结尾的情况下,arr[0...i]中的最长递增子序列长度。方法一:复杂度O(n^2)求解数组dp
dp[0] = 1,接下来从左向右依次算出以每个位置的数结尾的情况下,最长递增子序列长度;
假设计算到位置i,求以arr[i]为结尾的情况下最长递增子序列长度dp[i]。如果最长递增子序列以arr[i]结尾,那么在arr[0...i-1]中,所有比arr[i]小的数都可以作为倒数第二个数。这么多倒数第二个数的选择中,以哪个数结尾的最长递增子序列长度更大,就选那个数作为倒数第二数。所以,dp[i] = max(dp[j]+1, (0 <= j < i && arr[j] < arr[i]));
如果arr[0...i-1]中的数都大于arr[i],则dp[i] = 1:
方法二:
在上个方法中,我们用线性复杂度求出arr[0...i-1]中作为倒数第二个数。此步骤可以利用二分的思想降低到O(logn);
代码
/* 4.5 最长递增子序列 给定一个整数序列arr,长度为N,找到最长上升子序列(LIS),返回LIS的长度。 举例: 给出 [5,4,1,2,3],LIS 是 [1,2,3],返回 3 给出 [4,2,4,5,3,7],LIS 是 [4,4,5,7],返回 4 */ #include <iostream> #include <cstdlib> #include <vector> #include <algorithm> using namespace std; //O(n^2)的复杂度 vector<int> getDp1(vector<int> &nums) { if (nums.empty()) { return vector<int>(); }//if int len = nums.size(); vector<int> dp(len, 0); for (int i = 0; i < len; ++i) { dp[i] = 1; for (int j = 0; j < i; ++j) { if (nums[i] >= nums[j]) { dp[i] = max(dp[i], dp[j] + 1); }//if }//for }//for return dp; } //O(nlogn)的复杂度(针对不含重复元素的最长递增子序列) vector<int> getDp2(vector<int> &nums) { if (nums.empty()) { return vector<int>(); }//if int len = nums.size(); vector<int> dp(len, 0), ends(len, 0); dp[0] = 1; ends[0] = nums[0]; int right = 0; int l = 0, r = 0, m = 0; for (int i = 1; i < len; ++i) { l = 0; r = right; /*采用二分的思想,降低复杂度*/ while (l <= r) { m = (l + r) / 2; if (nums[i] < ends[m]) { l = m + 1; }//if else { r = m - 1; }//else }//while right = max(right, l); ends[l] = nums[i]; dp[i] = l + 1; }//for return dp; } //动态规划 int longestIncreasingSubsequence(vector<int> nums) { // write your code here if (nums.empty()) { return 0; }//if vector<int> dp = getDp1(nums); int maxLen = 0, len = dp.size(); for (int i = 0; i < len; ++i) { if (dp[i] > maxLen) { maxLen = dp[i]; }//if }//for return maxLen; } int main() { vector<int> v = { 5,4,1,2,3 }; cout << longestIncreasingSubsequence(v) << endl; system("pause"); return 0; }GitHub源码
相关文章推荐
- Linux的inode的理解
- C语言 斐波那契数列
- python的编码问题2
- CMake入门指南-编译教程
- R文本处理
- UISegmentedControl
- bzoj 2298: [HAOI2011]problem a
- 用JAXP对xml文档进行DOM编程
- opencv-python 摄像头的简单应用
- html5绘制文字
- bzoj 2190: [SDOI2008]仪仗队
- 全文索引----中文分词器mmseg4j
- C#目录操作 Path类与Directory类
- NYOJ - 171 聪明的kk
- CMake入门指南-编译教程
- Session里存的密码或其他信息如何获取。
- bzoj 4403: 序列统计
- Qt CS架构 客户端代码编写技巧 QTcpSocket
- 程序员日常
- lintcode_单词切分