zoukankan      html  css  js  c++  java
  • 最长上升子序列

    合唱队形题

    题目分析 :分别求最长上升和下降子序列。

    题目分析 :这道题差不多是个水题了,不过我在做题的被误导了,虽然结果正确却超时了。我们用上升子序列的时间复杂度是:O(n*n);

    题目收获 :需要对时间复杂和空间复杂度进行深刻的重新理解。

    AC代码 :

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #define maxn 105
    using namespace std;
    int d[maxn],b[maxn],num;
    int pepo[maxn];
    
    int main()
    {
        //freopen("in.txt", "r", stdin);
        scanf("%d", &num);
        memset(d, 0, sizeof(d));
        memset(b, 0, sizeof(b));
        for (int i = 1; i <= num; i++)
            scanf("%d", &pepo[i]);
        for (int i = 2; i <= num; i++)
            for (int j = 1; j < i; j++)
                if (pepo[i] > pepo[j])
                    d[i] = max(d[i], d[j] + 1);
        for (int i = num - 1; i >= 1; i--)
            for (int j = num; j > i; j--)
                if (pepo[i] > pepo[j])
                    b[i] = max(b[i], b[j] + 1);
        int ans = 0;
        for (int i = 1; i <= num; i++)
            ans = max(ans, b[i] + d[i]);
        printf("%d
    ", num - ans - 1);
            return 0;
    }
    View Code

    然,我在参考他人的代码时发现,还存在一种时间复杂度为O(n*logn)的算法,这就给我们一个面对大量数据时,不用担心超时的问题。假设一组数p[]={2 1 5 3 6 4 8 9 7} ,现在求它的上升子序列。

    我们用b[0]存p[0],即b[0]=2;

    然后发现1<2,所以b[0]=p[1]=1;被替换掉了。

    我们知道5>1,b[0+1]=b[1]=p[2]=5;此时b[]={1,5};

    到了p[3]=3<5;我们继续替换b[2]=p[3]=3;此时b[]={1,3};

    又到6>3,b[2+1]=b[3]=p[4]=6;此时b[]={1,3,6};

    一次推下去知道,b[]={1,3,4,8,9}

    最后发现:7<9;所以我们8替换为7.(这样做的目的是为了在后面加数字的时候任可以保持正确性)

    代码实现:二分法。

    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    const int maxn = 105;
    int fup[maxn],fdown[maxn],p[maxn];
    
    int search(int x, int y,int num)
    {
        int mid = 0;
        while (x < y)
        {
            if (num > fup[mid = (x + y) >> 1])//二分求num值应该在的位置
                x = mid + 1;
            else
                y = mid;
        }
        return x;
    }
    
    int main()
    {
        freopen("in.txt", "r", stdin);
        int t, k = 0;
        while (cin >>t && t)
        {
            memset(fup, 0, sizeof(fup));
            memset(fdown, 0, sizeof(fdown));
            memset(p, 0, sizeof(p));
            for (int i = 0; i < t; i++)
                scanf("%d", &p[i]);
            int j = 1;//初始化位置;
            for (int i = 0; i < t; i++)//从0开始遍历
            {
                if (fup[k = search(0, j - 1, p[i])] >= p[i])
                    fup[k] = p[i];
                else
                    fup[j++] = p[i];
            }
    
        }
        return 0;
    }
    View Code
  • 相关阅读:
    ClientDataSet 心得
    TClientDataSet中关于TField、TFieldDef动态创立字段的应用
    Delphi CxGrid 汇总(4)
    Delphi CxGrid 汇总(3)
    Delphi CxGrid 汇总(2)
    Delphi cxGrid使用汇总(一)
    修改后的SQL分页存储过程,利用2分法,支持排序
    字符串操作之格式化
    关于 cxGrid 的过滤问题
    cxGrid实现取消过滤和排序后定位到首行(单选和多选)
  • 原文地址:https://www.cnblogs.com/7750-13/p/7395663.html
Copyright © 2011-2022 走看看