这里需要注意的问题是:
寻找的是
前i个数字中最长上升子序列的长度,
还是
以第i个数字为结尾的最长上升子序列的长度
题目:
已知一个未排序的数组,求这个数组最长上升子序列的长度,
例如[1,3,2,3,1,4],
答案:4
dp方法,时间复杂度O(n2)
#include<stdio.h>
#include<iostream>
#include<vector>
using namespace std;
class Solution{
public:
int lengthOfLIS(vector<int>& nums){
if(nums.size()==0){
return 0;
}
vector<int> dp(nums.size(),0);
dp[0]=1;
int LIS=1;
for(int i=1;i<dp.size();i++){
dp[i]=1;
for(int j=0;j<i;j++){
if(nums[i]>nums[j]&&dp[i]<dp[j]+1){
dp[i]=dp[j]+1;
}
}
if(LIS<dp[i]){
LIS=dp[i];
}
}
return LIS;
}
};
int main(){
int test[]={1,3,2,3,1,4};
vector<int> nums;
for(int i=0;i<6;i++){
nums.push_back(test[i]);
}
Solution solve;
printf("%d\n",solve.lengthOfLIS(nums));
return 0;
}
通过设置一个栈(使用vector实现)stack,
stack[i]代表长度为i+1的上升子序列最后一个元素的最小可能取值,
即若要组成长度为i+2的上升子序列,需要一个大于stack[i]的元素,最终栈的大小,
即为最长上升子序列的长度。
时间复杂度:O(n2),
如果查找通过二分查找来实现则时间复杂度:O(nlogn)
不通过二分查找
#include<stdio.h>
#include<iostream>
#include<vector>
using namespace std;
class Solution{
public:
int lengthOfLIS(vector<int>& nums){
if(nums.size()==0){
return 0;
}
vector<int> stack;
stack.push_back(nums[0]);
for(int i=1;i<nums.size();i++){
if(nums[i]>stack.back()){
stack.push_back(nums[i]);
}
else{
for(int j=0;j<stack.size();j++){
if(stack[j]>=nums[i]){
stack[j]=nums[i];
break;
}
}
}
}
return stack.size();
}
};//类最后是有分号的
int main(){
int test[]={1,3,2,3,1,4};
vector<int> nums;
for(int i=0;i<6;i++){
nums.push_back(test[i]);
}
Solution solve;
cout<<"this is a new one"<<endl;
printf("%d\n",solve.lengthOfLIS(nums));
return 0;
}
这是我经历的第一次算法优化工作,纪念一下
通过二分查找:
#include<stdio.h>
#include<iostream>
#include<vector>
using namespace std;
int Binary_Search(vector<int> nums,int target){
int index=-1;
int begin=0;
int end=nums.size()-1;
//这个循环真的是精髓
while(index==-1){
int mid=(begin+end)/2;
if(target==nums[mid]){
index=mid;
}
else if(target<nums[mid]){
if(mid==0||target>nums[mid-1]){
index=mid;
}
end=mid-1;
}
else if(target>nums[mid]){
if(mid==nums.size()-1||target<nums[mid+1]){
index=mid+1;
}
begin=mid+1;
}
}
return index;
};
class Solution{
public:
int lengthOfLIS(vector<int>& nums){
if(nums.size()==0){
return 0;
}
vector<int> stack;
stack.push_back(nums[0]);
for(int i=1;i<nums.size();i++){
if(nums[i]>stack.back()){
stack.push_back(nums[i]);
}
else{
int pos=Binary_Search(stack,nums[i]);
stack[pos]=nums[i];
}
}
return stack.size();
}
};//类最后是有分号的
int main(){
int test[]={1,3,2,3,1,4};
vector<int> nums;
for(int i=0;i<6;i++){
nums.push_back(test[i]);
}
Solution solve;
cout<<"this is one for BS"<<endl;
printf("%d\n",solve.lengthOfLIS(nums));
return 0;
}