小米OJ-4-最长连续数列

描述

输入一个乱序的连续数列,输出其中最长连续数列长度,要求算法复杂度为 O(n) 。

输入

54,55,300,12,56

输出

3

输入样例

100,4,200,1,3,2

54,55,300,12

1

5,4,3,2,1

1,2,3,4,5,6

输出样例

4

2

1

5

6


解析:这里的最长连续数列不是最大上升/下降子序列,而是连续整数数列,又因为有复杂度O(n)限制,不能通过排序后计数的方式。


查阅资料之后发现了一种使用map关联容器来高效查找同时计数的算法。

[小米OJ] 4. 最长连续数列 - Rh's blog - CSDN博客


#include 

using namespace std;

int main()

{

    string input;

    while (cin >> input)

    {

        istringstream iss(input);

        string temp;

        vector vec;

        map mapping;

        int maxNum = -1;

        while (getline(iss, temp, ','))

        {

            vec.push_back(atoi(temp.c_str()));

            mapping[atoi(temp.c_str())] = 0;

        }

        for (auto c : vec)

        {

            if (mapping[c] == 0)

            {

                mapping[c] = 1;

                if (mapping.count(c - 1))

                {

                    mapping[c] += mapping[c - 1];

                }

                if (mapping.count(c + 1))

                {

                    mapping[c] += mapping[c + 1];

                }

                maxNum = maxNum > mapping[c] ? maxNum : mapping[c];

            }

        }

        cout << maxNum << endl;

    }

    return 0;

}

但是这种算法对于一些特定顺序的数列计算无效,如5,3,4,2。原因是在判断过程中只判断了前后各一个数及其连续数列长度,而又不能对错误的数列计数进行更新,所以这种算法是无效的。


求最长连续数列长度 - weixin_33946020的博客 - CSDN博客

之后结合了这篇博客中的算法思想,将计算连续数列的过程以当前分析的数为中心分成左右两个数列,并在查找计数的过程中将成功计入的数用erase弹出容器(避免重复计数),最后将左右两个数列相加,得到当前数所在连续队列的队长。最终利用set关联容器的高效查找能力完成了这个题目。


#include 

using namespace std;

int main()

{

    string input;

    while (cin >> input)

    {

        istringstream iss(input);

        string temp;

        //存放数列

        vector vec;

        //用set容器高效查找关键字,‘关键字’对应数的具体数值的字符串形式

        set setting;

        int maxNum = -1;

        while (getline(iss, temp, ','))

        {

            vec.push_back(atoi(temp.c_str()));

            setting.insert(atoi(temp.c_str()));

        }

        for (auto &c : vec)
        {
            if(setting.count(c))
            {
                int leftlength = 0;
                int rightlength = 0;
                int leftKey = c - 1;
                int rightKey = c + 1;
                while (setting.count(leftKey))                              //map.count(k),返回关键字为k的元素的数量,这里判断是否存在
                {
                    setting.erase(leftKey);                                 //map.erase(k),删除关键字为k的元素。可以作为返回值(size_type)记录所删除元素的数量
                    leftlength++;
                    leftKey -= 1;
                }
                while (setting.count(rightKey))
                {
                    setting.erase(rightKey);
                    rightlength++;
                    rightKey += 1;
                }
                maxNum = maxNum > (leftlength+rightlength+1) ? maxNum : (leftlength+rightlength+1);
            }
        }

        cout << maxNum << endl;

    }

    return 0;

}

你可能感兴趣的:(小米OJ-4-最长连续数列)