zoukankan      html  css  js  c++  java
  • 【动态规划专题】7:最长递增子序列

    《程序员代码面试指南--IT名企算法与数据结构题目最优解》 左程云 著

    最长递增子序列

    【题目】
    给定数组arr,返回arr的最长递增子序列

    【举例】
    arr=[2,1,5,3,6,4,8,9,7],返回的最长递增子序列为[1,3,4,8,9]

    【要求】
    如果arr长度为N,请实现时间复杂度为O(NlogN)的方法

    #include <iostream>
    #include <vector>
    #include <algorithm>
    #include <stdlib.h>
    using namespace std;
    
    
    void Printdp(int ** dp, int rows, int cols)
    {
        cout << "Printdp--------------start" << endl;
        for (int i = 0; i < rows; i++)
        {
            for (int j = 0; j < cols; j++)
            {
                cout << dp[i][j] << ",";
            }
            cout << endl;
        }
        cout << "Printdp--------------End" << endl;
        cout << endl;
    }
    
    int MaxNum(int A, int B)
    {
        if (A > B)
        {
            return A;
        }
        else
        {
            return B;
        }
    }
    void generateLIS(int *arr, int length, int* dp)
    {
        int len = 0;
        int index = 0;
        for (int i = 0; i < length; i++)
        {
            if (dp[i]>len)
            {
                len = dp[i];
                index = i;
            }
        }
    
        int *outlist = new int[len];
        int iOutIndex = len;
        outlist[--iOutIndex] = arr[index];
        for (int i = index; i >= 0; i--)
        {
            if (arr[i] < arr[index] && dp[i] == dp[index] - 1)
            {
                outlist[--iOutIndex] = arr[i];
                index = i;
            }
        }
    
        /////output result
        cout << "<<<<<< output result >>>>>" << endl;
        for (int i = 0; i < len; i++)
        {
            cout << outlist[i] << ",";
        }
        cout << endl;
    }
    /////这种获取dp数组的时间复杂度为O(N^2)
    void getdp1(int* arr, int length, int *dp )
    {
        for (int i = 0; i < length; i++)
        {
            dp[i] = 1;
            for (int j = 0; j < i; j++)
            {
                if (arr[j] < arr[i])
                {
                    dp[i] = MaxNum(dp[i], dp[j] + 1);
                }
            }
        }
    
        cout << "dp------------print" << endl;
        for (int i = 0; i < length; i++)
        {
            cout << dp[i] << ", ";
        }
        cout << endl;
    }
    
    
    void list1(int *arr, int length)
    {
        if (arr == nullptr || length <= 0)
        {
            return ;
        }
    
        int* dp = new int[length];
    
        getdp1(arr, length, dp);
        generateLIS(arr, length, dp);
    }
    /////////////////////////////////////////////////////对getdp函数做优化
    ////二分查找,将时间复杂度降为了 O(NlogN) 
    void getdp2(int* arr, int length, int *dp)
    {
        int* ends = new int[length];
        ends[0] = arr[0];
        dp[0] = 1;
        int right = 0;
        int L = 0;
        int R = 0;
        int M = 0;
        for (int i = 1; i < length; i++)
        {
            L = 0;
            R = right;
    
            /////二分查找
            while (L <= R)
            {
                M = (L + R) / 2;
                if (arr[i]>ends[M])
                {
                    L = M + 1;
                }
                else
                {
                    R = M - 1;
                }
            }
    
            right = MaxNum(right, L);
            ends[L] = arr[i];
            dp[i] = L + 1;
    
    
            /////////////////////////////////////////////
            cout << "ends["<<i<<"]: ";
            for (int k = 0; k < i; k++)
            {
                cout << ends[k] << ",";
            }
            cout << endl << endl;
            cout << "dp[" << i << "]: ";
            for (int k = 0; k < i; k++)
            {
                cout << dp[k] << ",";
            }
            cout << endl <<"---->>>>>>><<<<<<<<--------"<< endl;
            int abcde = 0;
        }
    
    
        cout << "dp------------print" << endl;
        for (int i = 0; i < length; i++)
        {
            cout << dp[i] << ", ";
        }
        cout << endl;
    }
    
    
    void list2(int *arr, int length)
    {
        if (arr == nullptr || length <= 0)
        {
            return;
        }
    
        int* dp = new int[length];
    
        getdp2(arr, length, dp);
        generateLIS(arr, length, dp);
    }
    ////===============测试用例====================
    void test1()
    {
        int arr[] = { 2, 1, 5, 3, 6, 4, 8, 9, 7 };
        //list1(arr, sizeof(arr) / sizeof(int));
    
        list2(arr, sizeof(arr) / sizeof(int));
    }
    
    void test2()
    {
        int arr[] = {12, 122, 2, 1, 3,5,7,101,102,103,9,11,104,105,12,15,17,20,100,200};
        list1(arr, sizeof(arr) / sizeof(int));
    
        list2(arr, sizeof(arr) / sizeof(int));///error
    }
    
    
    void test3()
    {
        int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
        list1(arr, sizeof(arr) / sizeof(int));
    
        list2(arr, sizeof(arr) / sizeof(int));
    }
    
    void test4()
    {
        int arr[] = { 7,6,5,4,3,2,1 };
        list1(arr, sizeof(arr) / sizeof(int));
        list2(arr, sizeof(arr) / sizeof(int));
    }
    int main()
    {
        test1();
        test2();
        test3();
        test4();
    
    
        cout << endl;
        system("pause");
        return 0;
    }

    算法思考:

    getdp1(), getdp2(),这2中获取 dp[ ]  数组 的方式,非常值得思考和借鉴。

  • 相关阅读:
    使用nodejs消费SAP Cloud for Customer上的Web service
    如何在SAP Cloud for Customer自定义BO中创建访问控制
    SAP云平台运行环境Cloud Foundry和Neo的区别
    SAP成都研究院马洪波:提升学习力,增强竞争力,收获一生乐趣
    SAP Netweaver的负载均衡消息服务器 vs CloudFoundry的App Router
    写在Github被微软收购之际
    在SAP云平台的CloudFoundry环境下消费ABAP On-Premise OData服务
    Java实现 LeetCode 517 超级洗衣机
    Java实现 LeetCode 517 超级洗衣机
    Java实现 LeetCode 517 超级洗衣机
  • 原文地址:https://www.cnblogs.com/music-liang/p/12145440.html
Copyright © 2011-2022 走看看