您的位置:首页 > 其它

最长单调"连续"递增子序列

2011-10-08 01:08 274 查看
#include <iostream>
#define N 9  //数组长度

//计算序列a
的最长单调连续递增子序列,设最长序列为a[i]~a[j];
template <class T>
void Longest(int& besti, int& bestj, int n, T a[]) {

int max=0;

for (int k=0; k<n; k++) {
//以k为头的子序列
for (int m=k; m<n; m++ ) {
//以m为尾的子序列
if (a[m+1]>=a[m]) //单调递增时,序列长度加1.
continue;

else {
if (max < m-k) {
max = m-k ;
besti = k;
bestj = m;
}
k = m; //从第m+1位置(即下一个递增序列)开始,重新计算子序列。
break; //(此轮循环结束后会自增1,所以从k=m,即从m+1开始。)
}
}
}

} //最好算法时间复杂度为O(n)(即整个序列递增时);最坏算法时间复杂度为O(n^2)(即整个序列递减时)

int main (int argc, const char * argv[])
{
int a
={-43,56,67,78,2,3,8,8,9};
int besti,bestj;
Longest(besti,bestj,N,a);
std::cout << std::endl <<"最长单调递增子序列的下标为: " <<besti << " " << bestj;

return 0;
}


此算法,几经修改,最终做了一个O(n^2)算法的,后续会继续更新。下一次目标,时间复杂度为O(nlogn)。

更新:

虽然没有能够做出nlogn的算法。但是做了另一个方法。

/**
*基于空间换时间的思想
*b
用于存放连续递增序列的个数
*如:
*a
: -43 56 67 78 2 3 8 8 9
*b
:   1  2  3  4 1 2 3 4 5
*最后重新扫描一遍b
,找到b
最大值,根据b
的下标即可求得连续递增序列的下标.
*算法时间复杂度O(n) ,空间复杂度O(n)
*/

#include <iostream>
#define N 9

template <class T>
void Longest(int& besti, int& bestj, int n,T a[])
{
/**
*besti为列头,bestj为列尾
*/
int b
;
int j=1;//存放于b[]中的值。
for (int i=0; i<n; i++) {
if ( a[i] <= a[i+1] ) {
b[i] = j++;
}
else {
b[i] = j;//递增序列的最后一个元素

j = 1;
b[i+1] = j; //下一个递增序列的第一个元素
}
}

long int max=-999999;//很小的数.

for (int k=0; k<n; k++) {
if ( b[k]>max ) {
max = b[k];
bestj = k;//记下最大值的下标,即:最长递增序列的列尾下标。
}
}

/**
* 最长递增序列的列头下标
*/
besti = bestj - b[bestj] + 1;
}

int main (int argc, const char * argv[])
{
int a
= {-43,56,67,78,2,3,8,8,9};
int besti = 0,bestj = 0;
Longest(besti,bestj,N,a);
std::cout << std::endl <<"最长单调递增子序列的下标为: " <<besti << " " << bestj << std::endl;
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法 class include