• 最长递增子序列


    问题描述:

        求数组中最长递增子序列

        例如:

            1,-1,2,-3,4,-5,6,-7

             最长递增子序列为:1,2,4,6

    问题解决:

           对于这类最优化问题,可以考虑使用动态规划,需要查看问题是否满足动态规划的最优化原理和无后效性。显然最长递增子序列中的部分子序列也是最长递增子序列,满足最优化原理

    无后效性,对于最长递增子序列中的元素,其前面的元素,不会影响到其后的元素,满足无后效性,因此可以使用动态规划。

    方法一:

        将数组从小到大排序,设为arrayB,求解原数组arrayA的最长递增子序列的问题转换为求解arrayA与arrayB的最长公共子序列,复杂度O(nlogn+n^2)=O(n^2)

    方法二:

        设数组array[]中前i个元素的最长递增子序列长度为LIS[i],那么

    LIS[i+1]=max{1,LIS[k]+1},for any k<=i & array[i+1]>array[k]

    方法三:

        方法二考察第i+1个元素时没有考虑前i个元素的分布,现在考虑前i个元素的分布。假设LIS[i]表示数组array[]中前i个元素最长递增子序列长度,MaxV[j],表示长度为j的所有递增子序列中最大值的最小值,那么:

        对前i个元素的任何一个递增子序列,如果这个子序列的最大元素比array[i+1]小,则将array[i+1]添加到该子序列中,构成一个新的递增子序列。

    具体实现:

    /**
    *    求解数组的最长递增子序列
    *    
    *    问题满足动态规划的最优化原理和无后效性,可以使用动态规划来求解
    *
    *    假设在目标数组array[]的前i个元素中,最长递增子序列长度为LIS[i],那么:
    *    LIS[i+1]=max{1,LIS[k]+1},array[i+1]>array[k],for any k<=i 也就是说,如果array[i+1]
    *    大于array[k],那么第i+1个元素可以接在LIS[k]长的子序列后面构成一个更长的子序列。
    *    array[i+1]本身至少可以构成一个长度为1的子序列。
    */
    
    #include <iostream>
    using namespace std;
    
    int MaxLIS(int* array,int size)
    {
        int max=array[0];
        for (int i=0;i<size;i++)
        {
            max=array[i]>max?array[i]:max;
        }
        return max;
    }
    
    /**
    *    方法1:求解最长递增子序列的算法,复杂度O(N^2)
    *    求解思路:
    *        LIS[i+1]=max{1,LIS[k]+1},for any k<=i
    */
    int LIS1(int array[],int size)
    {
        int* LIS=new int[size];
        for (int i=0;i<size;i++)
        {
            LIS[i]=1;
            //执行:LIS[i+1]=max{1,LIS[k]+1},for any k<=i
            for (int j=0;j<i;j++)
            {
                if (array[i]>array[j]&&LIS[j]+1>LIS[i])
                {
                    LIS[i]=LIS[j]+1;
                }
            }
        }
    
        return MaxLIS(LIS,size);
    }
    
    
    /**
    *    方法2:求解最长递增子序列算法2,复杂度O(N^2)
    *    求解思路:
    *        方法1,考察第i+1个元素的时候,没有考虑前i个元素的分布情况。现在考察第i+1个元素
    *        的时候考虑前面i个元素的情况,即对于前面i个元素的任何一个递增子序列,如果这个子序列的
    *        最大的元素比array[i+1]小,则将array[i+1]添加到这个子序列的后面,构成一个新的递增子序列
    */
    int LIS2(int* array,int size)
    {
        int* maxV=new int[size+1];    //记录长度为k的子序列的最大元素为maxV[k]
        maxV[1]=array[0];
        maxV[0]=array[0]-1;    //简化数组
    
        int* LIS=new int[size];
        for (int i=0;i<size;i++)
        {
            LIS[i]=1;
        }
    
        int nmaxLIS=1;    //最长递增子序列长度
        for (int i=0;i<size;i++)
        {
            int j=nmaxLIS;
            //寻找array[i]需要添加的最长递增子序列
            for (;j>=0;j--)
            {
                if (array[i]>maxV[j])
                {
                    LIS[i]=j+1;
                    break;
                }
            }
    
            //array[i]添加到当前最长递增子序列
            if (LIS[i]>nmaxLIS)
            {
                nmaxLIS=LIS[i];
                maxV[nmaxLIS]=array[i];
            }
            else     //更新指定最长递增子序列长度,其中maxV[j]<array[i]<maxV[j+1]
            {
                maxV[j+1]=array[i];
            }
        }
    
        return nmaxLIS;
    }
    
    int main()
    {
        int array[]={1,-1,2,-3,4,-5,6,-7};
        int size=sizeof(array)/sizeof(array[0]);
    
        cout<<"最长递增子序列长度Method1:"<<LIS1(array,size)<<endl;
        cout<<"最长递增子序列长度Method2:"<<LIS2(array,size)<<endl;
    }
  • 相关阅读:
    安装APK失败,错误代码:INSTALL_FAILED_INVALID_APK 解决方案
    android保持服务不休眠(持续运行)以及唤醒屏幕的方法
    判断Android 当前版本是否为debug版本
    Android 使用WebView加载含有Canvas的页面截屏处理
    喜大普奔,微软Microsoft JDBC Driver For SQL Server已发布到maven中央仓库
    系统架构设计理论与原则、负载均衡及高可用系统设计速记
    Sharing A Powerful Tool For Application Auto Monitor
    Sharing A Powerful Tool For Calculate Code Lines
    关于GC和析构函数的一个趣题
    垃圾回收机制GC知识再总结兼谈如何用好GC
  • 原文地址:https://www.cnblogs.com/luosongchao/p/3551445.html
Copyright © 2020-2023  润新知