您的位置:首页 > 其它

算法题-数组的最长递增子序列

2014-09-27 02:14 204 查看
题目

给定一个无序的数组,返回其中最长递增子序列的长度。

解法

利用一个辅助数组1,记录每个长度的LIS的结尾字符,最后其长度就是所求值;

辅助数组2,与1同步变化,记录数组1中每个元素在输入序列中的原始下标;

辅助数组3,与输入数组等长,记录每个元素在一个LIS中的前驱下标。

代码

int binSearch(const vector<int> &tail, int len, int key)  //辅助函数,二分查找,找出key或者第一个大于key的下标
{
int left = 0, right = len - 1;
int mid;

while(left <= right)
{
mid = left + ((right - left) >> 1);
if(tail[mid] == key)
return mid;
else if(tail[mid] > key)
right = mid - 1;
else
left = mid + 1;
}

return left;  //如果不存在key,则返回第一个大于key的元素下标
}

void LIS(int *a, int n)
{
vector<int> tail(n); //辅助数组1,当前每个LIS子序列的结尾字符,递增的
vector<int> orig(n); //辅助数组2,与数组1同步变化,当前结尾在原始数组的下标
vector<int> prev(n); //辅助数组3,与输入等长,当前结尾字符的上一元素在原始输入中的下标
int len = 0;

tail[0] = a[0];  //初值
orig[0] = 0;
prev[0] = -1;
++len;

for(int i = 1; i < n; ++i)
{
if(a[i] > tail[len - 1])  //直接添加在尾部,LIS长度+1
{
tail[len] = a[i];
orig[len] = i;
prev[i]   = orig[len - 1];

++len;
}
else
{
int pos = binSearch(tail, len, a[i]);
tail[pos] = a[i];  //替换掉一个字符
orig[pos] = i;
prev[i]   = pos > 0 ? orig[pos - 1] : -1;
}
}

stack<int> stk;  //用栈,因为记录的路径是逆序的
for(int cur = orig[len - 1]; cur >= 0; cur = prev[cur])
{
stk.push(a[cur]);
}

cout << len << endl;
while(!stk.empty())
{
cout << stk.top() << ' ';
stk.pop();
}
cout << endl;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐