java中最长上升子数列是什么_最长上升子序列的动态规划的O(n^2)求解和贪心O(nlgn)求解 | 学步园...

题目描述:

给你一个数列,一次操作是指将某个数移到数列中别的位置上去,然后问最少要几次操作才能让数列变得有序。例如,数列7,1,3,2,6,5就只需要三次移动,把3移到2后面,把5移到6前面,再把7移到最后面即可。

问题等价转化:

其实就是一个最长上升子序列问题。因为整个操作过程实质上可以等价地看作是,把要移动的数先全部取出来,再挨个放回适当的位置。这就要求取出要移动的数后,剩下的那些数本身是有序的。若希望要移动的数越少越好,那也就等于说是剩下的不动的数要越多越好。

最长上升子序列问题:

给出一个由n个数组成的序列x[1..n],找出它的最长单调上升子序列。即求最大的m和a1,

a2……,am,使得a1

动态规划求解思路分析:(O(n^2))

经典的O(n^2)的动态规划

贪心+二分查找:(O(nlogn))

开辟一个栈,每次取栈顶元素s和读到的元素a做比较,如果a>s,  则加入栈;如果a

这也是很好理解的,对x和y,如果x

举例:原序列为1,5,8,3,6,7

栈为1,5,8,此时读到3,则用3替换5,得到栈中元素为1,3,8,  再读6,用6替换8,得到1,3,6,再读7,得到最终栈为1,3,6,7  ,最长递增子序列为长度4。

代码:

#include

using namespace std;

//DP:dp[i] = max{1,dp[j]+1} (j=1,2, ...,i-1,且A[j]

template

int Lis_Dp(T seq[],int n)

{

int *dp=new int[n];

memset(dp,0,n*sizeof(int));

dp[0]=1;

for(int i=1;i

{

int max=1;

for(int j=0;j

{

if(seq[j]

{

if(max

max=dp[j]+1;

}

}

dp[i]=max;

}

int ret=dp[n-1];

delete[] dp;

return ret;

}

template

int Lis_Greedy(T seq[],int n)

{

int top=0;

int *stack=new int[n];

memset(stack,0,n*sizeof(int));

stack[top]=seq[0];

for(int i=1;i

{

int low=0,high=top;

while(low<=high)

{

int mid=(low+high)/2;

if(stack[mid]

low=mid+1;

else

high=mid-1;

}

if(low==top+1)

top++;

stack[low]=seq[i];

}

delete[] stack;

return top+1;

}

int _tmain(int argc, _TCHAR* argv[])

{

int testdata[10]={4,6,3,2,5,1,5,7,9,8};

cout<

cout<

system("pause");

return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值