在C中找到两倍数字的最快方法[重复]
Posted
技术标签:
【中文标题】在C中找到两倍数字的最快方法[重复]【英文标题】:Fastest way to find twice number in C [duplicate] 【发布时间】:2016-09-16 13:50:50 【问题描述】:谁能帮助我如何用 C 解决这个代码?我认为我必须使用大 O 表示法作为解决方案,但我对此一无所知。
问题:有一个大小为 N+1 的数组 T,其中从 1 到 N 的数字是随机的。一个数字 x 重复两次(位置也是随机的)。
找到这个数字 x 值的最快方法应该是什么?
例如: N = 7
[6 3 5 1 3 7 4 2]
x=3
【问题讨论】:
你对内存使用有限制吗? 可能相关:Bucket Sort 数组包含 1,2,3,...,N,K,其中 K 在 1,2,3,...,N 中。求 1..N 和然后从 1..K. 的总和中减去它。 有几种 O(n) 方法可以做到这一点。我怀疑它可以做得更快。 【参考方案1】:数字 1..N 的总和是 N*(N+1)/2。
所以,额外的数字是:
extra_number = sum(all N+1 numbers) - N*(N+1)/2
除了总和之外,一切都是 O(1)。总和可以在 O(N) 时间内计算出来。
整体算法是O(N)。
【讨论】:
这是一道标准的面试题。对于额外的学分,您需要考虑当总和溢出整数类型时会发生什么。 为了好玩,只要您采取措施避免 N*(N+1)/2 的计算溢出(通过更改计算步骤取决于 N 是奇数还是偶数)。【参考方案2】:使用该值作为下一个数组索引(减 1)遍历数组,用特殊值(如 0 或否定)标记访问过的数组。 O(n)
平均,只有一半的元素被访问。
v
6 3 5 1 3 7 4 2
v
. 3 5 1 3 7 4 2
v
. 3 5 1 3 7 . 2
v
. 3 5 1 . 7 . 2
v
. 3 5 . . 7 . 2
v !! all ready visited. Previous 3 is repeated.
. 3 5 . . 7 . 2
加起来不会引起溢出问题。当然需要修改数组(或者需要一个兄弟bool
标志数组。)
即使重复超过 1 个值,此方法也有效。
【讨论】:
【参考方案3】:Klaus 给出的算法有 O(1) 的内存需求,但需要对给定数组中的所有元素求和,这可能非常大,无法对它们进行迭代(求和)。
另一种方法是遍历数组并在每次迭代中增加一次出现计数器,因此算法可以在找到重复项后立即停止,尽管最坏的情况是扫描所有元素。例如:
#define N 8
int T[N] = 6, 3, 5, 1, 3, 7, 4, 2;
int occurences[N+1] = 0;
int duplicate = -1;
for (int i = 0; i < N; i++)
occurences[T[i]]++;
if (occurences[T[i]] == 2)
duplicate = T[i];
break;
请注意,此方法也不受整数溢出的影响,即N*(N+1)/2.
可能大于整数数据类型所能容纳的大小。
【讨论】:
注意:对于算法,只有复杂性是相关的。如果性能很关键,则必须进行衡量(这里,访问一半的元素会带来成本:条件、额外的数据访问) @DieterLücking:是的,通常算法是 O(n)。一个令人愉快的特性是它不受整数限制的影响:N*(N+1)/2
在某些情况下可能会溢出。以上是关于在C中找到两倍数字的最快方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章