[300]Longest Increasing Subsequence
2015-11-03 20:20
489 查看
【题目描述】
Given an unsorted array of integers, find the length of longest increasing subsequence.
For example,
Given
The longest increasing subsequence is
is
for you to return the length.
Your algorithm should run in O(n2) complexity.
Follow up: Could you improve it to O(n log n) time complexity?
【思路】
经典的最长子序列的题目。
第一种方法是o(n^2)的。len[i]表示到nums[i]结尾的序列中最长递增子序列的长度,pre[i]记录的是该最长递增子序列结尾的元素的下标。如果比i小的j中有满足对应最长递增子序列结尾的元素比nums[i]小,而且len[j]+1>len[i],那么则更新pre[i]和len[i],同时和maxnum比较,如果比maxnum大,更新maxnum,遍历结束的时候返回maxnum。
第二种方法是对第一种方法的改进,因为采用了二分搜索,所以是O(nlogn)的。pre[i]里记录的是长度为i的最长递增子序列结尾的元素。给pre[0]赋值无限小,pre[1]赋值nums[0],从第二个元素开始遍历,对于第i个元素,对长度为0到maxlen的最长子序列进行二分搜索,找到长度最长的且结尾元素即pre[j]比num[i]小的最长子序列,更新长度为j+1的结尾元素为nums[i],并且把长度与maxlen比较,如果大于则更新maxlen。结束时返回maxlen。
【代码】
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n=nums.size();
if(n==0) return 0;
vector<int> pre(n,0);
vector<int> len(n,1);
int maxnum=1;
for(int i=0;i<n;i++){
pre[i]=i;
}
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(nums[i]>nums[pre[j]]&&len[j]+1>len[i]){
pre[i]=i;
len[i]=len[j]+1;
if(maxnum<len[i]){
maxnum=len[i];
}
}
}
}
return maxnum;
}
};
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n=nums.size();
if(n==0) return 0;
vector<int> pre(n,0);
//vector<int> len(n,1);
//int maxnum=1;
pre[0]=INT_MIN;
pre[1]=nums[0];
int low,high,mid;
int maxlen=1;
for(int i=1;i<n;i++){
low=0;
high=maxlen;
while(low<=high){
mid=(low+high)/2;
if(nums[i]>pre[mid]) low=mid+1;
else high=mid-1;
}
pre[low]=nums[i];
if(low>maxlen) maxlen++;
}
return maxlen;
}
};
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.
Follow up: Could you improve it to O(n log n) time complexity?
【思路】
经典的最长子序列的题目。
第一种方法是o(n^2)的。len[i]表示到nums[i]结尾的序列中最长递增子序列的长度,pre[i]记录的是该最长递增子序列结尾的元素的下标。如果比i小的j中有满足对应最长递增子序列结尾的元素比nums[i]小,而且len[j]+1>len[i],那么则更新pre[i]和len[i],同时和maxnum比较,如果比maxnum大,更新maxnum,遍历结束的时候返回maxnum。
第二种方法是对第一种方法的改进,因为采用了二分搜索,所以是O(nlogn)的。pre[i]里记录的是长度为i的最长递增子序列结尾的元素。给pre[0]赋值无限小,pre[1]赋值nums[0],从第二个元素开始遍历,对于第i个元素,对长度为0到maxlen的最长子序列进行二分搜索,找到长度最长的且结尾元素即pre[j]比num[i]小的最长子序列,更新长度为j+1的结尾元素为nums[i],并且把长度与maxlen比较,如果大于则更新maxlen。结束时返回maxlen。
【代码】
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n=nums.size();
if(n==0) return 0;
vector<int> pre(n,0);
vector<int> len(n,1);
int maxnum=1;
for(int i=0;i<n;i++){
pre[i]=i;
}
for(int i=1;i<n;i++){
for(int j=0;j<i;j++){
if(nums[i]>nums[pre[j]]&&len[j]+1>len[i]){
pre[i]=i;
len[i]=len[j]+1;
if(maxnum<len[i]){
maxnum=len[i];
}
}
}
}
return maxnum;
}
};
class Solution {
public:
int lengthOfLIS(vector<int>& nums) {
int n=nums.size();
if(n==0) return 0;
vector<int> pre(n,0);
//vector<int> len(n,1);
//int maxnum=1;
pre[0]=INT_MIN;
pre[1]=nums[0];
int low,high,mid;
int maxlen=1;
for(int i=1;i<n;i++){
low=0;
high=maxlen;
while(low<=high){
mid=(low+high)/2;
if(nums[i]>pre[mid]) low=mid+1;
else high=mid-1;
}
pre[low]=nums[i];
if(low>maxlen) maxlen++;
}
return maxlen;
}
};
相关文章推荐
- Dwz(J-UI)框架--入门
- UIView convertRect
- Android_uiautomator支持输入中文
- getRequestDispatcher()与sendRedirect()的区别
- [LeetCode] Longest Increasing Subsequence
- 利用insert,update和delete注入获取数据
- lock_guard和unique_lock的区别
- Codeforces Round #328 (Div. 2) B. The Monster and the Squirrel (规律)
- android中子线程更新UI的方式浅析
- iOS(9) SDWebImage 里面给 UIImageView 加载图片的逻辑是什么样的
- Kqueue 实现非阻塞 Socket 通信
- HDU 5531 Rebuild
- Android Bluetooth Low Energy(Android低功耗蓝牙)
- Arduino小车学习与研究博客
- protocol isis issues(续1.2----地址转化相关)
- [转]runOnUiThread 、 Handler 对比(一)
- Source Code Tags and Builds
- USB core(一) - rh_queue_status与rh_call_control
- Deploy .Net project automatically with MsBuild and MsDeploy (0)
- uitableview使用优化