zoukankan      html  css  js  c++  java
  • 最长上升子序列(Longest increasing subsequence)


    问题描述
            对于一串数A={a1a2a3…an},它的子序列为S={s1s2s3…sn},满足{s1<s2<s3<…<sm}。求A的最长子序列的长度。

    动态规划法

    算法描述:
            设数串的长度为n,L[i]为以第i个数为末尾的最长上升子序列的长度,a[i]为数串的第i个数。
            L[i]的计算方法为:从前i-1个数中找出满足a[j]<a[i](1<=j<i)条件的最大的L[j],L[i]等于L[j]+1。
    动态规划表达式:


    代码实现:

    int LIS(int a[], int n)
    {
        int len[MAXSIZE];
        int i, j;
        int maxlen = 0;
        //计算以第i个数为结尾的最长上升子序列的长度
        for (i = 1; i <= n; i++)
        {
            len[i] = 0;
            //从前i-1个数中找出满足a[j]<a[i](1<=j<i)条件的最大的L[j]
            for (j = i-1; j >= 1; j--)
            {
                if (a[j] < a[i] && len[j] > len[i])
                {
                    len[i] = len[j];
                }
            }
            len[i]++;
     
            if (len[i] > maxlen)
            {
                maxlen = len[i];
            }
        }
        return maxlen;
    }


    上述算法的时间复杂度为O(n2)。

    改进算法:
            在从前i-1个数中找出满足a[j]<a[i](1<=j<i)条件的最大的L[j]的时间复杂度为O(n),这里采用二分查找的方法对它进行优化,使其复杂度降为O(nlogn)。
            增设一个m[]数组,m[x]存放长度为x的最长上升子序列的最小末尾数。例:m[3] = 17表示长度为3的最长上升子序列的最小末尾数为17。
            由于子序列是上升的,所以m数组中的元素有一个性质,当x<y时,m[x]<m[y],利用这个性质来使用二分查找。
    设m数组所存储的最长上升子序列的长度为k,当前计算的数为第i个
    如果a[i]>m[k],则m[++k]=a[i];
    否则在m[1~k]内二分查找小于(等于)a[i]的最大值的位置p,m[p]=a[i]。

    代码实现:

    int BSearch(int a[], int n, int t)
    {
        int low = 1;
        int high = n;
        
        while (low <= high)
        {
            int mid = (low + high) / 2;
            if (t == a[mid])
            {
                return mid;
            }
            else if (t > a[mid])
            {
                low = mid + 1;
            }
            else
            {
                high = mid - 1;
            }
        }
        return low;
    }
     
    int LIS_BSearch(int a[], int m[], int n)
    {
        int maxlen = 1;        //最长上升子序列的长度
        m[maxlen] = a[1];
     
        int i;
        for (i = 2; i <= n; i++)
        {
            if (a[i] > m[maxlen])
            {
                m[++maxlen] = a[i];
            }
            else
            {
                //返回小于a[i]的最大值的位置p
                int p = BSearch(m, maxlen, a[i]);
                m[p] = a[i];
            }
        }
        return maxlen;
    }


    改进后的算法时间复杂度为O(nlogn)。
     

  • 相关阅读:
    Android网络项目课程笔记-----系统设置_首选项框架&Holo风格的设置
    Android网络项目课程笔记-----加载数据
    Android网络项目课程笔记-----代码复用性
    Android网络项目课程笔记-----AdapterView嵌套
    Android网络项目课程笔记-----滑动Banner
    Android网络项目课程笔记-----滑动Tab&Banner
    Android网络项目课程笔记-----页面结构
    Android网络项目课程笔记-----欢迎页面新手引导
    C#调用SAP S4/HANA Gateway Service
    CefSharp试用
  • 原文地址:https://www.cnblogs.com/DWVictor/p/10279676.html
Copyright © 2011-2022 走看看