重新创建序列

时间:2014-05-06 09:35:03

标签: algorithm integer sequence

我遇到了以下问题,从那时起我一直在想这个问题:

Alice在黑板上写了N个连续的正整数。例如。 "99, 100, 101, 102"。 Bob从每个数字中删除了所有数字,但是一个数字,所以序列现在可以读取,例如"9, 0, 0, 1"。请注意,他留下的数字对于每个整数都可以是不同的数字。

我们的任务是,在O(N log N)时间复杂度,找到可能已启动序列的最小数字。在上面的例子中,答案是99。对于长度为7的序列"1, 4, 0, 5, 4, 1, 4",答案为1042。 (产生序列1042,1043,1044,1045,1046,1047,1048)。

我可以显示大约1234567890*N的上限,因此输出的大小不限。但是,我甚至无法找到有效的O(N^2)解决方案。

有什么想法吗?

1 个答案:

答案 0 :(得分:7)

更新:对于有兴趣的人,此问题出现在Baltic Olympiad in Informatics (BOI) 2014中(它是任务"序列")。 Due to Codeforces user Fdg,这是一个O(N log N)解决方案:尝试起始值的每个可能的最后一位数。将连续的数组元素分成最后有数字0到9的组(这可以从起始值'最后一位数字推断出来)。我们知道在删除最后一个数字后,同一组中的所有值都具有相同的前缀。让我们消除输入中的数字与 根据其位置匹配的最后一位数匹配的所有值。

现在我们有一个稍微不同的子问题:对于每组10个,我们知道其前缀中出现的 set 数字。我们将其折叠为单个数组元素。这个广义问题只有原问题大小的十分之一,并且可以递归地使用相同的算法来解决。

我们得到递归T(N)= 10 * T(N / 10)+ O(N),我们用主定理求解为T(N)= O(N log N)。

示例:

我们说输入为[1, 4, 0, 5, 4, 1, 4, 9, 5, 0, 1, 0]。因此,在通用形式中,我们知道每个位置的以下数字子集:

{1} {4} {0} {5} {4} {1} {4} {9} {5} {0} {1} {0}

我们检查号码2作为起始号码的最后一位数(当然我们也会检查所有其他数字,但这个分支将包含最小解决方案)。我们知道最后一位数的序列就像

2  3  4  5  6  7  8  9  0  1  2  3

所以我们知道具有相同前缀的组(2-9和0-3)。我们还从已知的集合中删除了那些位于正确位置的数字:

{1} {4} {0} {} {4} {1} {4} {} | {5} {0} {1} {0}

通过收集每组的所有数字,我们得出了减少的问题

{0,1,4} {0,1,5}

我们再次暴力强制倒数第二位。我们说我们正在检查4。我们得到:

  4     5
{0,1} {0,1}

减少到

{0,1}

现在我们只有一个数组元素,我们只需要在那些没有前导零的数字中构建按字典顺序排列的最小数字,即10。结果是1042

旧版

我相信这里的一个关键观察是,在这样的进展中,长度为N,只有最后一个ceil(log_10(N))数字被改变不止一次。因此,我们可以强制执行最后一个ceil(log_10(N))数字,前缀末尾的9个数字以及O(N * log N)之前的数字。

所以我们修复了模式

P..PX9..9S...S

在已知后缀S的情况下,已知9的数量,X <1。 9是已知的,但前缀P不是。

我们现在可以从已经与我们已知的其中一个数字相匹配的序列中删除这些数字。我们留下一组数字,我们知道它们包含前缀P.我们只是形成字典上最小的字符串,它没有前导零并包含所有数字。

运行时为O(N ^ 2 log N)。