最长上升子序列问题LIS

问题描述(poj2533):对于给定的n个整数A1, A2…An, 从左到右的顺序选择尽可能多的数,组成一个上升子序列。(上升子序列可以理解为:删除0个或多个数, 其他数的顺序不变, 例如1, 6, 2, 3, 7, 5, 可以选出上升子序列1, 2, 3, 5 也可以选出 1, 6, 7)
poj2533 : 求最长上升子序列的长度
法一:通过DP记忆化搜索求解问题,时间复杂度为O(n^2)

#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include <algorithm>
using namespace std;

int n, m, i, j, mx;
const int maxn = 1010;
int a[maxn], d[maxn];

//记忆化搜索
//状态:d[i]:第i个数的最长子序列的长度
//状态转移为d[i] = max(d[i], d[j] + 1);
int main()
{
    while(~scanf("%d",&n)){              //共有n个数
        for(i = 0; i < n;i++)           //录入n个数保存在数组a[]中
            scanf("%d",&a[i]);
        for (i = 0; i < n; i++)
        {
            d[i] = 1;                              //初始化数组d[]为1,
            for(j = 0;j < i;j++)
                if(a[j] < a[i])
                    d[i] = max(d[i], d[j] + 1); //第i个数的最长子序列长度 等于 比 第i个数小 的 数的最长子序列加1
        }
        mx = 0;
        for(i = 0;i < n;i++)
            mx = max (mx ,d[i]);
        printf("%d\n",mx);
    }
    return 0;
}

法二:用DP二分搜索解决问题降低时间复杂度,该方法的时间复杂度为O(nlogn)
实现:开一个栈,每次取栈顶元素top和读到的元素temp做比较,如果temp > top 则将temp入栈;如果temp < top则二分查找栈中的比temp大的第1个数,并用temp替换它。 最长序列长度即为栈的大小top。
举例:原序列为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。
如果想要输出最长有序子数列的话,可以在法二的基础上稍作改动。
用一个b【i】记录第i个元素在队列中的位置,然后逆向寻找,依次输出。

//二分搜索
#include <iostream>
#define SIZE 1001

using namespace std;

int main()
{
    int i, j, n, top, temp;
    int stack[SIZE];
    cin >> n;

    top = 0;
    stack[0] = -1;//令栈顶元素为-1
    for (i = 0; i < n; i++)
    {
        cin >> temp;
        /* 比栈顶元素大数就入栈 */
        if (temp > stack[top])
        {
            stack[++top] = temp;
        }
        else
        {
            int low = 1, high = top;
            int mid;
            /* 二分检索栈中比temp大的第一个数 */
            while (low <= high)
            {
                mid = (low + high) / 2;
                if (temp > stack[mid])
                {
                    low = mid + 1;
                }
                else
                {
                    high = mid - 1;
                }
            }
            /* 用temp替换 */
            stack[low] = temp;
        }
    }

    /* 最长序列数就是栈的大小 */
    cout << top << endl;

    //system("pause");
    return 0;
}

发布了47 篇原创文章 · 获赞 6 · 访问量 1万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章