题目:
http://blog.csdn.net/michael_kong_nju/article/details/44851495
这是一家互联网公司的笔试题,好像没有说保密协议,应该是可以公开的,我也来贡献一下自己的思路和代码。
分布式系统中的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. 为该算法设计并实现单元测试
算法思路:
假设数组是a, index从0开始,数组长度为n,
value表示1,2,3...n这么多的值. set<int>st 用来保存当前提前出现的value.
1. 循环 index 从0 到 n-1,value从1到n,
如果当前的 index+1 和 value 是相同的例如 a[0] = 1 , 那么直接打印输出并换行。
2. 如果不同,那么肯定是index+1大于value的情况了,这种是属于乱序的。此时将出现的值 a[index] 放入 set 里面。例如在index = 2
的位置将5放入set,后面再将8,10,4放入set,index继续向后。但是value是不变的,即我要一直找到那个a[index] = value的那个值。
3.如果在后面的位置遍历的时候找到相同的了,即出现a[index] = value 了。 此时肯定是index + 1 > value. 即在index位应该出现的是
index + 1 而不是这个很小的value.此时,打印这个value,并且在set里面循环查找是不是有value的下一个值出现,如果有那么直接+逗号,
同行输出,注意这里最大是找到index + 1,因为不可能出现比他还大的值。如果在找到index+1之前没有出现在set里面那么从步骤1开始
继续当前的index往后找,即在原数组中找。
算法大概就是这样,
下面是实现:
int RPC_seq(int a[], int n) { if (n == 0 || a == NULL) { cout << "Error in input!" << endl; return -1; } int value = 1; set<int>st; for (int i = 0; i < n; i++) { if (a[i] == value && i + 1 == value) //直接打印输出 cout << value++ << endl; else if (a[i] == value) //这个是在后面找到了value的值 { cout << value++ << ","; while (value <= i + 1) { if (st.find(value) != st.end()) //依次输出value后面的值。 { cout << value << ","; st.erase(value++); } else { cout << endl; break; } } } else st.insert(a[i]); } return 0; } int main(void) { //int a[10] = { 1, 2, 5, 8, 10, 4, 3, 6, 9, 7 }; int a[10] = { 1, 2, 8,5, 7, 4, 3, 10,6,9 }; RPC_seq(a, 10); }