zoukankan      html  css  js  c++  java
  • LIS学习笔记(两种算法)O(n^2) 和 O(nlogn)

    2017-09-02 10:34:21

    writer:pprp

    最长上升子序列,具体分析看代码:O(n^2)的做法,dp的思想

    分析:每次读一个进行扫描,如果当前读入的这个要比之前的大,

    说明有可能加一,所以对当前读入这个之前的元素进行扫描,

    扫描到的值加上当前这个值跟该出的值进行比对,确定更大的值

    关键代码表示如下:

    if( i < n && arr[i] < arr[n] )
        f(n) = max(f(i))+ 1;

    代码如下:

    /*
    @theme:LIS最长上升子序列
    @writer:pprp
    @begin:10:00
    @end:10:15
    @declare复杂度为O(n^2)
    @error:dp[i] = MAX(dp[j]+1,dp[i]),dp[i] = 1初始化为1
    @date:2017/9/2
    */
    
    #include <bits/stdc++.h>
    
    using namespace std;
    
    /*
    未优化的最长上升子序列
    f(i)代表从头到i的位置最长上升子序列的长度
    if( i < n && arr[i] < arr[n] )
        f(n) = max(f(i))+ 1;
    dp[i]是如果取到arr[i]的时候的最长上升子序列
    */
    
    int dp[10010],arr[10010];
    
    int MAX(int a, int b)
    {
        return a > b ? a : b;
    }
    
    int main()
    {
        int N;
        while(cin >> N && N)
        {
            int max = 0;
            for(int i = 0 ; i < N ;i++)
            {
                dp[i] = 1;
                cin >> arr[i];
                for(int j = 0 ;j < i ; j++)
                {
                    if(arr[j] < arr[i])
                        dp[i] = MAX(dp[j] + 1, dp[i]);
                }
                max = MAX(max,dp[i]);
            }
            cout << max << endl;
        }
        return 0;
    }

    2、采用了优化,记录了可能被选中的点,将其记录在tmp数组中,再从从其中进行查找O(nlog(n))

    tmp数组中储存的是对于长度i的lLIS他最小可能的结果,当然是这个数越小越容易得到最大结果了...

    /*
    @theme:tmp最长上升子序列
    @writer:pprp
    @begin:10:00
    @end:14:32
    @declare复杂度为O(n^2)
    @error:dp[i] = MAX(dp[j]+1,dp[i]),dp[i] = 1初始化为1
    @date:2017/9/2
    */
    
    #include <bits/stdc++.h>
    
    using namespace std;
    
    int arr[10010],tmp[10010];
    int len;
    
    /*
    状态定义:用到tmp数组
    tmp[i]:代表的是对于所有长度为i的LIS,他的结果最小有可能是多少,
           如果越小那就越容易被取到
    tmp中的元素是严格递增的
    状态转移:
            if( dp[j] = i )
                tmp[i] = min(arr[j])
    结果查找--用二分的方法去找
    if(tmp[i] < arr[n] && tmp[i+1] >= arr[n] )
        f[n] = i+1 .... i 代表的是长度
    
    */
    
    //二分查找,在tmp中进行二分查找arr[i]
    //对tmp数组进行更新
    void bisearch(int x)
    {
        int left=1,mid,right=len;
        while(left<=right)
        {
            mid=(left+right)>>1;
            if(tmp[mid]<x)
                left=mid+1;
            else
                right=mid-1;
        }
        tmp[left]=x;
    }
    
    int main()
    {
        int N;
        while(cin >> N && N)
        {
            len=1;
            cin >> arr[0];
            tmp[len]=arr[0];
    
            for(int i=1; i<N; i++)
            {
                scanf("%d",&arr[i]);
    
                if(arr[i] > tmp[len])//如果当前i指向的arr的值大于tmp当前的值
                {
                    len++;
                    tmp[len]=arr[i];
                }//向tmp数组中加入arr的值
                else
                    bisearch(arr[i]);//在tmp中进行查找找到的就将其更新
                //如果用lower_bound的话就这样:
                //*lower_bound(tmp,tmp+len,arr[i]) = arr[i];
            }
            printf("%d
    ",len);
        }
        return 0;
    }

     其他图片参考:

  • 相关阅读:
    git log后怎么退出?
    nuxt项目中怎么使用iconfont图标
    navicat连接远程数据库mysql报错2013解决方法
    navicat15激活使用
    picgo软件使用
    设置yarn源修改为淘宝源
    nuxt项目修改本地运行的端口
    nuxt项目中使用less全局样式、全局变量的配置
    带环链表 linked list cycle
    Delete a Node in Single Linked List删除单链列表中的节点
  • 原文地址:https://www.cnblogs.com/pprp/p/7466674.html
Copyright © 2011-2022 走看看