有一个由n个数字组成的数组.一个数字重复n/2次,而其他n/2个数字是不同的

There is an array of n numbers. One number is repeated n/2 times and other n/2 numbers are distinct

本文关键字:数字 2次 其他 是不同 2个 数组 有一个 一个      更新时间:2023-10-16

有一个由n个数字组成的数组。一个数字重复n/2次,而其他n/2个数字是不同的。找出重复的数字。(最佳解决方案是o(n)恰好是n/2+1比较。)

这里的主要问题是n/2+1比较。我有两个O(n)的解,但它们进行了n/2+1以上的比较。

1> 把数组的个数分成三组。对任何相同的元素,把那n/3组分成。例如数组是(1 10 3)(4 8 1)(1 1)。。。。因此所需的比较次数为7,即大于n/2+1即8/2+1=5

2> 将a[i]与a[i+1]和a[i+2]进行比较例如阵列是8 10 3 4 1 1 1

总共9个比较

我很感激哪怕是一点点帮助。谢谢

空间复杂度为O(1)。

当然,如果其他所有对都不同,则只需比较所有对。如果你找到一对有两个相等数字的,你就得到了这个数字

假设你有这样的数字(这只是关于索引)

[1,2,3,4,5,6,7,8,9,10]

然后你可以像这个一样进行n/2+1比较

(1,2),(3,4),(5,6),(7,8),(9,7),(9,8)

如果所有对都不同,则返回10。

重点是,当你比较最后4个剩下的数字(7,8,9,10)时,你知道其中至少有两个相同的数字,你有3个比较。

您只需要找到数组中存在两次的数字。

你只是从头开始,保留一个哈希或你已经看到的数字,当你得到一个出现两次的数字时,就停止。

最糟糕的猫场景:你首先看到所有n/2个不同的数字,然后下一个数字是重复的n/2+2(因为您要查找的数字不是n/2唯一数字的一部分)

阅读关于O(1)空间复杂性的部分为时已晚,但无论如何,这里是我的解决方案:

#include <iterator>
#include <unordered_set>
template <typename ForwardIterator>
ForwardIterator find_repeated_element(ForwardIterator begin, ForwardIterator end)
{
    typedef typename std::iterator_traits<ForwardIterator>::value_type value_type;
    std::unordered_set<value_type> visited_elements;
    for (; begin != end; ++begin)
    {
        bool could_insert = visited_elements.insert(*begin).second;
        if (!could_insert) return begin;
    }
    return end;
}
#include <iostream>
int main()
{
    int test[] = {8, 10, 3, 4, 1, 1, 1, 1};
    int* end = test + sizeof test / sizeof *test;
    int* p = find_repeated_element(test, end);
    if (p == end)
    {
        std::cout << "the was no repeated elementn";
    }
    else
    {
        std::cout << "repeated element: " << *p << "n";
    }
}

由于Pigeon-hole原理,您只需要测试数组的前n/2+1个成员,因为某些重复次数将至少重复两次。循环遍历每个成员,使用哈希表进行跟踪,并在某个成员重复两次时停止。

O(n)(但不完全是n/2+1)的另一个解决方案,但具有O(1)空间:

因为你有这个数字的n/2,所以如果你把它看作一个排序的数组,它的位置有两个场景:

要么它是最低的数字,所以它将占据1-n/2的位置。。或者它不是,然后确定它在位置n/2+1。

因此,您可以使用选择算法,并检索4个元素:大小为[(n/2-1),(n/2+1)]的范围
我们想要k的大小,所以算法可以。

然后,在这4个数字中重复的数字必须至少是两次(简单检查)

所以总复杂度:4*O(n)+O(1)=O(n)

关于复杂性O(n/2+1)和空间复杂性O(1),您可以(几乎)满足这种方法的要求:

比较元组:

a[x]==a[x+1]、a[x+2]==a[g+3]。。。a[n-1]==a[n]

如果未找到匹配项,则增加步骤:

a[x]==a[x+2],a[x+1]==a[g+3]

在最坏的情况下,当您有这样的数组时,这将在O(n/2+2)中运行(但始终在O(1)空间中):[8 1 10 1 3 1 4 1]

qsort( )阵列然后扫描第一次重复。