读书人

最长递加子序列及应用

发布时间: 2012-09-04 14:19:30 作者: rapoo

最长递增子序列及应用

最长递增子序列

输入序列X:5,9,4,8,3,7,6,10,则输出该序列的最长递增子序列的长度为3,其中一个最长递增子序列为5,9,10.

两种思路(基于动态规划方法求解)

思路1 将序列X递增排序为序列Y:3,4,5,6,7,8,9,10,原问题就转化成求X,Y两个序列的最长公共子序列问题.(本文不提供具体解法)

思路2 设f[i]表示以下标i结尾的最长递增子序列的长度

则: f[0] = 1 for i = 0

f[i] = max{max{f[j]+1 | 0=< j < i 且X[j] <= X[i]} , 1} for 0 < i < n

设pre[i]表示以下标i结尾的最长递增子序列中下标i对应的元素的前驱元素对应的下标(-1表示没有前驱)

例:5,9,4,8,3,7,6,10

f[0] = 1 pre[0] = -1 5(序列)

f[1] = 2 pre[1] = 0 5,9

f[2] = 1 pre[2] = -1 4

f[3] = 2 pre[3] = 0 5,8

f[4] = 1 pre[4] = -1 3

f[5] = 2 pre[5] = 0 5,7

f[6] = 2 pre[6] = 0 5,6

f[7] = 3 pre[7] = 1 5,9,10

则最长递增子序列的长度为3,其中一个最长递增子序列为5,9,10(通过pre构造).

具体代码实现如下:

/************************************************************************//* Input: (ht,wt)          (65,100) (70,150) (56,90) (75,90) (60,95) (68,110)    Output: longest tower 6           (56,90) (60,95) (65,100) (68,110) (70,150) (75,190)          *//************************************************************************/struct Person{int m_ht;  //身高int m_wt;  //体重};//比较算子,以身高优先比较,在身高相同的情况下比较体重int compare(const void* p1, const void* p2){int x1 = ((Person*)p1)->m_ht;int y1 = ((Person*)p1)->m_wt;int x2 = ((Person*)p2)->m_ht;int y2 = ((Person*)p2)->m_wt;if(x1 > x2){return 1;}else if(x1 == x2){return y1-y2 >= 0 ? !!(y1-y2) : -1;}else{return -1;}}int getLargestNumOfPeople(Person* pPerson, int n, Person* pRes){if(pPerson == NULL || pRes == NULL || n <= 0) return -1;int* pWt = new int[n];qsort(pPerson,n,sizeof(Person),compare);for(int i = 0; i < n; ++i){pWt[i] = pPerson[i].m_wt;}int* nPreIndx = new int[n];int index;int largestN = maxIncreaseSubSequence(pWt,n,nPreIndx,index);int* pMaxSub = MISubSequence(nPreIndx,index);int j = 0;for(i = pMaxSub[0]; i > 0; --i,++j){pRes[j] = pPerson[pMaxSub[i]];}delete[] pMaxSub;return largestN;}



读书人网 >其他相关

热点推荐