您的位置:首页 > 其它

最长递增子序列

2011-04-13 21:24 295 查看
方法一,转为求公共子序列
先对原序列进行排序
然后用对原序列和新序列求其最长公共子序列
所得即原序列的最长非递减子序列
注意,由于所求出来的是最长非递减子序列,所以可能和所要求的不一样,慎用

而且下面所示的代码用的是递归的方法来实现的,时间复杂度和空间复杂度都是O(2^N),真要实现的时候最好采用动态归化+滚动数组的方法

 

实现代码:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
template<typename InIt>
size_t LCS( InIt _First1, InIt _Last1, InIt _First2, InIt _Last2 )
{
if( _First1 == _Last1 || _First2 == _Last2 )
{
return 0;
}

if( *_First1 == *_First2 )
{
return 1 + LCS( _First1 + 1, _Last1, _First2 + 1, _Last2 );
}
else
{
return max( LCS( _First1, _Last1, _First2 + 1, _Last2 ),
LCS( _First1 + 1, _Last1, _First2, _Last2 ) );
}
}
int main()
{
int n = 0;
vector<int> array;
while( (cin >> n) && ( n != 0 ) ) array.push_back( n );
size_t m = 0;
cin >> m;

vector<int> arraySorted( array.begin(), array.end() );
sort( arraySorted.begin(), arraySorted.end() );

cout << LCS( array.begin(), array.end(), arraySorted.begin(), arraySorted.end() ) << endl;

return 0;
}
 

 

方法二:
方法二就是使用动态归化的方法
设L[i]为以第i个元素结尾的最长递增子序列的长度
最后在所有L[i]中取MAX即为所求 

template< typename T >
int LIS( T* array, int count )
{
if( count == 0 ) return 0;

vector<int> L( count, 1 );

for( int i = 1; i < count; i++ )
{
for( int j = 0; j < i; j++ )
{
if( array[i] > array[j] && L[j] + 1 > L[i] )
{
L[i] = L[j] + 1;
}
}
}

int maxL = 0;
for( int i = 0; i < count; i++ )
{
if( maxL < L[i] ) maxL = L[i];
}
return maxL;
}
 

 

方法三:
方法三和方法二类似,也是使用动态归化的方法
但不同之处是,使用L[i]表示,前i个元素中的最长递增子序列的长度
而且使用labels[i].pos表示,由i个元素组成的最长递增子序列的最后一个元素的位置,而且是所有最后一个元素中最小的一个
这样,其实会导致 i < j的时候 array[ labels[i].pos ] < array [ labels[j].pos ],即array[labels[i].pos]是一个单调递增函数
所以可以使用二分查找的方法,来找到第一个小于当前元素array[i]的array[ labels[i].pos ]的最大的i的位置

#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
using namespace std;
template<typename T>
struct Program
{
static vector<T> array;
static vector<int> parent;

struct Label
{
int pos;

Label(): pos( -1 ) {}
Label( int _pos ): pos( _pos ) {}

bool operator <( const Label& l ) const
{
if( pos == -1 && l.pos == -1 ) return false;
else if( pos == -1 ) return true;
else if( l.pos == -1 ) return false;
else return array[pos] < array[l.pos];
}
};
void LIS( size_t m = 0 )
{
if( array.empty() ) return;

vector<size_t> L( array.size(), 1 );
vector<Label> labels( array.size() + 1 );

labels[1].pos = 0;
size_t maxL = 1;
for( size_t i = 1; i < array.size(); i++ )
{
typename vector<Label>::const_iterator it = lower_bound( labels.begin(), labels.begin() + maxL + 1, Label( i ) );
int j = it - labels.begin() - 1;

L[i] = j + 1;
if( maxL < L[i] )
{
maxL = L[i];
labels[maxL].pos = i;
parent[i] = labels[j].pos;

}
else if( array[i] < array[labels[j + 1].pos] )
{
labels[j + 1].pos = i;
parent[i] = labels[j].pos;
}
}

vector<T> tracks;
int p = labels[maxL].pos;
while( p != -1 )
{
tracks.push_back( array[p] );
p = parent[p];
}

reverse_copy( tracks.begin(), tracks.end(), ostream_iterator<T>( cout, " " ) );
cout << endl;
}
};
template<typename T>
vector<T> Program<T>::array;
template<typename T>
vector<int> Program<T>::parent;
int main()
{
Program<int> p;
int n = 0;
while( (cin >> n) && ( n != 0 ) )
{
p.array.push_back( n );
p.parent.push_back( -1 );
}
p.LIS();
return 0;
}
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  iterator struct