在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中找到两倍数字的最快方法[重复]的主要内容,如果未能解决你的问题,请参考以下文章

检查数字是不是有小数的最快方法[重复]

使用 vanilla JS 删除 ES5 及更低版本数组中重复数字的最快方法是啥?

如何找到偶数或奇数“1”位[重复]

以最快的方式找到所有可能的子字符串[重复]

在 Access DB 中删除重复项的最快方法

在Java中创建长度为'x'的字符串的最快方法全部由char'c'组成[重复]