今天写一个问题的时候遇到最长上升子序列的问题
按照DP的搞法,dp[i]代表以第i个数结尾的最长上升子序列,
for(i=0;i<n;i++)
{
for(j=0;j<i;j++)
{
if(num[i]>num[j])
dp[i]=(dp[i])>(dp[j]+1)?(dp[i]):(dp[j]+1);
}
}
这样来做,但是O(n^2)的复杂度是能忍的么?
上网查了一下优化,发现一个使用贪心策略的O(nlogn)做法
具体做法是从头开始保存一个栈, 当遇到下一个数的时候,若栈顶元素小于这个数,把这个数入栈,如果栈顶元素小于这个数,二分查找栈中比此数大的第一个数,把这个数变小为新遇到的数。
举例:原序列为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。
这个算法可以这样理解:栈中同时维护了N个不同长度的上升序列,每种长度不同的序列都是在相同长度下尾部最小的序列。