阿里巴巴的一道笔试题

来源:互联网 发布:绝地求生优化补丁 编辑:程序博客网 时间:2024/04/30 16:41

分布式系统中的RPC请求经常出现乱序的情况。

写一个算法来将一个乱序的序列报序输出,列如,假设起始序号是1,对于(1,2,5,8,10,4,3,6,9,7)这个序列,输出是

1

2

3,4,5

6

7,8,9,10

上述例子中,3到来的时候发现4,5已经在了,因此将已经满足顺序的整个序列(3,4,5)输出为一行。


要求:

1.写一个高效的算法完成上述功能,实现要求尽可能的健壮,易于维护

2.为该算法完成单元测试。


我的思路肯定不是最佳的,只是实现了而已,如果有更好的思路和优化请发送到评论区,谢谢~

先说下我的思路:

题目说了是RPC请求,那么在发送过程中发送的包序号应该是1,2,3,4...,这里应该不用考虑丢包吧 - -。

那么这个乱序的序号,实际上就是顺序的序号打乱了,所以按顺序输出后不可能出现1,2,4,5...类似这种情况。

接着看给出的序列是1到10乱序,输出却是顺序的,只不过分块输出了。

看看输出结果可能没什么头绪,但是重点的一句话:

3到来发现4,5已经存在了,因此将满足顺序的整个序列(3,4,5) 输出为一行  

更重点的词:已经,满足顺序,一行。

已经存在说明3是在叫后面录入(分析的意思),4,5已经分析过了但是不满足输出条件而已。这里有个问题是为什么3到来发现4,5存在了输出,而不是4到来了发现

5已经存在了输出?

我认为1,2输出后,根据输出结果来看,是顺序输出的,肯定要输出3,所以一定要的等待3的出现才能顺序输出3,4,5。

那么我假设规则:依次读取每个数据,若读到的其中一个数据可以和前面输出过符合顺序则输出。

后面就好解释了,1,2,3,4,5输出后剩余序列8,10,6,9,7。

读入8,10,不符合,到6了,和已经输出过的3,4,5符合顺序序列,单独输出6。

剩余序列8,10,9,7。

很简单直到读到7符合条件输出顺序序列7,8,9,10。

以上就是我思考的过程。罗嗦了...


我的解决方案:

每次选择开头元素和此刻最小元素的一个区间,在这个区间的元素和最小的元素可以构成顺序序列则输出。

举个例子,假设序列剩余(5,8,10,4,3,6,9,7),那么最小的元素是3。

区间是(5,8,10,4,3)。

分析可得3,4,5顺序序列,输出即可。然后删除元素3,4,5,再次选取最小元素和区间就是6了。每次选取最小元素的区间就可以连接上已经输出过的,保证是顺序的。


代码:

#include <iostream>#include <vector>#include <algorithm>#include <set>int main(){    std::vector<int>ivec = {1,2,5,8,10,4,3,6,9,7};    std::set<int>iset;    while(!ivec.empty())       {        /* 选取最小元素 */        auto mid = min_element(ivec.begin(), ivec.end());        iset.insert(*mid);        /* 定义最小元素区间 */        std::vector<int>tmp(ivec.begin(), mid+1);        int t = *mid;        int del = *mid;        /* 查找和最小元素顺序的元素 */        while(1)        {            auto iter = find(tmp.begin(), tmp.end(), ++t);            if(iter != tmp.end())            {                iset.insert(*iter);                ivec.erase(remove(ivec.begin(), ivec.end(), t));            }            else            {                break;            }        }        ivec.erase(remove(ivec.begin(), ivec.end(), del));        /* 输出序列 */        auto end = --iset.end();        for(auto it = iset.begin(); it != end; ++it)        {            std::cout << *it << ",";        }        std::cout << *end << std::endl;;        iset.clear();    }}





            

1 0