Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 在数组中查找两个重复数字的算法,无需排序_Algorithm_Search - Fatal编程技术网

Algorithm 在数组中查找两个重复数字的算法,无需排序

Algorithm 在数组中查找两个重复数字的算法,无需排序,algorithm,search,Algorithm,Search,有一个大小为n的数组(数字介于0和n-3之间),只有2个数字重复。元素随机放置在数组中 例如{2,3,6,1,5,4,0,3,5}n=9,重复的数字是3和5 找到重复数字的最佳方法是什么 注意[您不应该使用排序]对数组排序似乎是最好的解决方案。一个简单的排序将使搜索变得微不足道,并将占用更少的时间/空间 否则,如果您知道数字的域,请创建一个包含那么多bucket的数组,并在遍历数组时递增每个bucket。大概是这样的: int count [10]; for (int i = 0; i <

有一个大小为n的数组(数字介于0和n-3之间),只有2个数字重复。元素随机放置在数组中

例如{2,3,6,1,5,4,0,3,5}n=9,重复的数字是3和5

找到重复数字的最佳方法是什么


注意[您不应该使用排序]

对数组排序似乎是最好的解决方案。一个简单的排序将使搜索变得微不足道,并将占用更少的时间/空间

否则,如果您知道数字的域,请创建一个包含那么多bucket的数组,并在遍历数组时递增每个bucket。大概是这样的:

int count [10];

for (int i = 0; i < arraylen; i++) {
    count[array[i]]++;
}
int计数[10];
for(int i=0;i

然后只需在数组中搜索任何大于1的数字。这些是有重复项的项目。只需要在原始数组中传递一次,在计数数组中传递一次。

对于每个数字:检查它是否存在于数组的其余部分。

将每个元素插入集合/哈希表中,首先检查它是否已经存在。

如果不进行排序,您将跟踪已访问的数字

在psuedocode中,这基本上是(这样做,所以我不只是给你答案):

如果您知道可能的输入域是什么,则有一个O(n)解决方案。例如,如果输入数组包含0到100之间的数字,请考虑下面的代码。
bool flags[100];
for(int i = 0; i < 100; i++)
    flags[i] = false;

for(int i = 0; i < input_size; i++)
    if(flags[input_array[i]])
         return input_array[i];
    else       
        flags[input_array[i]] = true;
bool标志[100];
对于(int i=0;i<100;i++)
标志[i]=假;
对于(int i=0;i

当然还有额外的内存,但这是最快的

检查这篇关于这个主题的旧而好的论文:

  • (PDF)

您可能能够利用总和(数组)=(n-2)*(n-3)/2+两个缺失的数字这一事实


编辑:正如其他人所指出的,结合平方和,你可以使用这个,我只是在计算中有点慢。

好的,似乎我就是不能休息一下:)

最简解 当然,你不会像数学课教你解平方方程那样去解它

首先,以2^32的模计算所有值,即允许溢出。
然后检查对{p,q}:{0,S1},{1,S1-1}。。。根据表达式(2)查找候选项(由于模和平方运算,可能有2个以上)
最后检查找到的候选对象是否真的存在于数组中两次。

这个怎么样:

for (i=0; i<n-1; i++) {
  for (j=i+1; j<n; j++) {
    if (a[i] == a[j]) {
        printf("%d appears more than once\n",a[i]);
        break;
    }
  }
}

for(i=0;i问题的一些答案:包含作为子问题的解决方案,您可以根据自己的目的采用这些解决方案

例如,这里有一个相关部分来自:

bool有多个重复项(int*a、int m、int n)
{
/**O(m)在时间上,O(1)在空间上(对于'typeof(m)==typeof(*a)==int')
[]数组是否有重复项。
前提条件:所有值都在[n,n+m)范围内。
功能:它使用符号位标记访问的项目。
*/
断言((INT_MIN-(INT_MIN-1))==1);//检查n==INT_MIN
对于(int*p=a;p!=&a[m];++p){
*p-=(n-1);//[n,n+m)->[1,m+1)
断言(*p>0);
}
//确定:是否存在重复项
bool has_dups=false;
对于(int i=0;i=0);
断言(j0)
a[j]*=-1;//标记
否则{//已经看到了
has_dups=true;
打破
}
}
//恢复阵列
对于(int*p=a;p!=&a[m];++p){
如果(*p<0)
*p*=-1;//取消标记
//[1,m+1)->[n,n+m)
*p+=(n-1);
}
返回已重复;
}
程序保持数组不变(数组应该是可写的,但其值在退出时恢复)


它适用于高达
INT_MAX
(在64位系统上为
9223372036854775807
)的数组大小。

您知道数组包含从0到n-3的每个数字以及两个重复的数字(p&q)。为简单起见,现在忽略0大小写

您可以计算数组上的和和与积,结果是:

1 + 2 + ... + n-3 + p + q = p + q + (n-3)(n-2)/2
如果你从整个数组的和中减去(n-3)(n-2)/2,你得到

sum(Array) - (n-3)(n-2)/2 = x = p + q
现在对产品执行相同的操作:

1 * 2 * ... * n - 3 * p * q = (n - 3)! * p * q

prod(Array) / (n - 3)! = y = p * q
您现在可以使用以下术语:

x = p + q

y = p * q

=> y(p + q) = x(p * q)

如果你转换这个术语,你应该能够计算p和q这是Python of的答案(它的一个修订版)的实现,它不使用模运算。它是一个单通算法,O(log(n))在空间中。如果固定宽度(例如32位)如果使用整数,则它只需要两个固定宽度的数字(例如,对于32位:一个64位数字和一个128位数字)。它可以处理任意大的整数序列(它一次读取一个整数,因此整个序列不需要存储在内存中)

例如:

>>> two_repeated([2, 3, 6, 1, 5, 4, 0, 3, 5])
(3, 5)
以上代码的更详细版本如下所示:

def two_repeated_seq(arr):
    """Return the only two duplicates from `arr`.

    >>> two_repeated_seq([2, 3, 6, 1, 5, 4, 0, 3, 5])
    (3, 5)
    """
    n = len(arr)
    assert all(0 <= i < n - 2 for i in arr) # all in range [0, n-2)
    assert len(set(arr)) == (n - 2) # number of unique items

    s1 = (n-2) + (n-1)       # s1 and s2 have ~ 2*(k+1) and 4*(k+1) digits  
    s2 = (n-2)**2 + (n-1)**2 # where k is a number of digits in `max(arr)`
    for i, j in enumerate(arr):
        s1 += j - i     
        s2 += j*j - i*i

    """
    s1 = (n-2) + (n-1) + sum(arr) - sum(range(n))
       = sum(arr) - sum(range(n-2))
       = sum(range(n-2)) + p + q - sum(range(n-2))
       = p + q
    """
    assert s1 == (sum(arr) - sum(range(n-2)))

    """
    s2 = (n-2)**2 + (n-1)**2 + sum(i*i for i in arr) - sum(i*i for i in range(n))
       = sum(i*i for i in arr) - sum(i*i for i in range(n-2))
       = p*p + q*q
    """
    assert s2 == (sum(i*i for i in arr) - sum(i*i for i in range(n-2)))

    """
    s1 = p+q
    -> s1**2 = (p+q)**2
    -> s1**2 = p*p + 2*p*q + q*q
    -> s1**2 - (p*p + q*q) = 2*p*q
    s2 = p*p + q*q
    -> p*q = (s1**2 - s2)/2

    Let C = p*q = (s1**2 - s2)/2 and B = p+q = s1 then from Viete theorem follows
    that p and q are roots of x**2 - B*x + C = 0
    -> p = (B + sqrtD) / 2
    -> q = (B - sqrtD) / 2
    where sqrtD = sqrt(B**2 - 4*C)

    -> p = (s1 + sqrt(2*s2 - s1**2))/2
    """
    sqrtD = (2*s2 - s1**2)**.5
    assert int(sqrtD)**2 == (2*s2 - s1**2) # perfect square
    sqrtD = int(sqrtD)
    assert (s1 - sqrtD) % 2 == 0 # even
    p = (s1 - sqrtD) // 2
    q = s1 - p
    assert q == ((s1 + sqrtD) // 2)
    assert sqrtD == (q - p)
    return p, q
def两次重复(arr):
“”“从'arr'返回仅有的两个副本。”。
>>>两个重复序列([2,3,6,1,5,4,0,3,5])
(3, 5)
"""
n=长度(arr)
断言所有(0)假设数组为
a[0]、a[1]、a[2]……a[n-1]
sumA=a[0]+a[1]+..+a[n-1]
sumASquare=a[0]*a[0]+a[1]*a[1]+a[2]*a[2]+..+a[n]*a[n]
sumFirstN=(N*(N+1))/2其中N=N-3所以
sumFirstN=(n-3)(n-2)/2
同样地
sumFirstNSquare=N*(N+1)*(2*N+1)/6=(N-3)(N-2)(2n-5)/6
假设重复的元素为=X和Y
所以X+Y=sumA-sumFirstN;
X*X+Y*Y=苏马斯广场-苏马斯广场;
通过解这个二次方程,我们可以得到X和Y的值。
时间复杂度=O(n)
空间复杂度=O(1)

对于(i=1;i为什么我们要尝试做数学(特别是解二次方程)这些都是昂贵的运算。解决这一问题的最佳方法是构造一个大小为(n-3)位的位图,即,(n-3)+7/8字节。最好对这个内存执行calloc,这样每个位都将
1 * 2 * ... * n - 3 * p * q = (n - 3)! * p * q

prod(Array) / (n - 3)! = y = p * q
x = p + q

y = p * q

=> y(p + q) = x(p * q)
def two_repeated(iterable):
    s1, s2 = 0, 0
    for i, j in enumerate(iterable):
        s1 += j - i     # number_of_digits(s1) ~ 2 * number_of_digits(i)
        s2 += j*j - i*i # number_of_digits(s2) ~ 4 * number_of_digits(i) 
    s1 += (i - 1) + i
    s2 += (i - 1)**2 + i**2

    p = (s1 - int((2*s2 - s1**2)**.5)) // 2 
    # `Decimal().sqrt()` could replace `int()**.5` for really large integers
    # or any function to compute integer square root
    return p, s1 - p
>>> two_repeated([2, 3, 6, 1, 5, 4, 0, 3, 5])
(3, 5)
def two_repeated_seq(arr):
    """Return the only two duplicates from `arr`.

    >>> two_repeated_seq([2, 3, 6, 1, 5, 4, 0, 3, 5])
    (3, 5)
    """
    n = len(arr)
    assert all(0 <= i < n - 2 for i in arr) # all in range [0, n-2)
    assert len(set(arr)) == (n - 2) # number of unique items

    s1 = (n-2) + (n-1)       # s1 and s2 have ~ 2*(k+1) and 4*(k+1) digits  
    s2 = (n-2)**2 + (n-1)**2 # where k is a number of digits in `max(arr)`
    for i, j in enumerate(arr):
        s1 += j - i     
        s2 += j*j - i*i

    """
    s1 = (n-2) + (n-1) + sum(arr) - sum(range(n))
       = sum(arr) - sum(range(n-2))
       = sum(range(n-2)) + p + q - sum(range(n-2))
       = p + q
    """
    assert s1 == (sum(arr) - sum(range(n-2)))

    """
    s2 = (n-2)**2 + (n-1)**2 + sum(i*i for i in arr) - sum(i*i for i in range(n))
       = sum(i*i for i in arr) - sum(i*i for i in range(n-2))
       = p*p + q*q
    """
    assert s2 == (sum(i*i for i in arr) - sum(i*i for i in range(n-2)))

    """
    s1 = p+q
    -> s1**2 = (p+q)**2
    -> s1**2 = p*p + 2*p*q + q*q
    -> s1**2 - (p*p + q*q) = 2*p*q
    s2 = p*p + q*q
    -> p*q = (s1**2 - s2)/2

    Let C = p*q = (s1**2 - s2)/2 and B = p+q = s1 then from Viete theorem follows
    that p and q are roots of x**2 - B*x + C = 0
    -> p = (B + sqrtD) / 2
    -> q = (B - sqrtD) / 2
    where sqrtD = sqrt(B**2 - 4*C)

    -> p = (s1 + sqrt(2*s2 - s1**2))/2
    """
    sqrtD = (2*s2 - s1**2)**.5
    assert int(sqrtD)**2 == (2*s2 - s1**2) # perfect square
    sqrtD = int(sqrtD)
    assert (s1 - sqrtD) % 2 == 0 # even
    p = (s1 - sqrtD) // 2
    q = s1 - p
    assert q == ((s1 + sqrtD) // 2)
    assert sqrtD == (q - p)
    return p, q
suppose array is a[0], a[1], a[2] ..... a[n-1] sumA = a[0] + a[1] +....+a[n-1] sumASquare = a[0]*a[0] + a[1]*a[1] + a[2]*a[2] + .... + a[n]*a[n] sumFirstN = (N*(N+1))/2 where N=n-3 so sumFirstN = (n-3)(n-2)/2 similarly sumFirstNSquare = N*(N+1)*(2*N+1)/6 = (n-3)(n-2)(2n-5)/6 Suppose repeated elements are = X and Y so X + Y = sumA - sumFirstN; X*X + Y*Y = sumASquare - sumFirstNSquare; So on solving this quadratic we can get value of X and Y. Time Complexity = O(n) space complexity = O(1)
for(i=1;i<=n;i++) {
  if(!(arr[i] ^ arr[i+1]))
        printf("Found Repeated number %5d",arr[i]);
}
int arr[] = {1,1,2,10,3,3,4,5,5,6,6};
using namespace std;

main()
{
    //int arr[] = {2, 9, 6, 1, 1, 4, 2, 3, 5};
    int arr[] = {1,1,2,10,3,3,4,5,5,6,6};

    int i = 0;

    vector<int> vec;

    int var = arr[0];
    for(i = 1 ; i < sizeof(arr)/sizeof(arr[0]); i += 2)
    {
            var = var ^ arr[i];

            if(var != 0 )
            {
                //put in vector
                var = arr[i-1];
                vec.push_back(var);
                i = i-1;
            }
            var = arr[i+1];
    }

    for(int i = 0 ; i < vec.size() ; i++)
        printf("value not repeated = %d\n",vec[i]);

}
value not repeated= 2

value not repeated= 10

value not repeated= 4
    int arr[] = {2, 3, 6, 1, 5, 4, 0, 3, 5};

    int num = 0, i;

    for (i=0; i < 8; i++)
         num = num ^ arr[i] ^i;
 int[] numArray = new int[] { 1, 2, 3, 4, 5, 7, 8, 3, 7 };

        for (int i = 0; i < numArray.Length; i++)
        {
            for (int j = i + 1; j < numArray.Length; j++)
            {
                if (numArray[i] == numArray[j])
                {
                   //DO SOMETHING
                }
            }
int[] array = { 1, 2, 3, 4, 5, 4, 4, 1, 8, 9, 23, 4, 6, 8, 9, 1,4 };
int[] myNewArray = null;
int a = 1;

 void GetDuplicates(int[] array)
    for (int i = 0; i < array.Length; i++)
            {
                for (int j = i + 1; j < array.Length; j++)
                {
                    if (array[i] == array[j])
                    {
                          a += 1;
                    }
                }
                Console.WriteLine(" {0} occurred {1} time/s", array[i], a);

                IEnumerable<int> num = from n in array where n != array[i] select n;
                 myNewArray = null;
                 a = 1;
                 myNewArray = num.ToArray() ;

                 break;

            }
             GetDuplicates(myNewArray);
Bucket 0 : Sum ( x where: x & 2 power 0 == 0 )
...
Bucket i : Sum ( x where: x & 2 power i == 0 )
A XOR B = Array[i] XOR Array[i-1] XOR ... 0, XOR n-3 XOR n-2  ... XOR 0
 for(i=0;i< n;i++)
 xor=xor^arr[i]
 for(i=1;i<=n-3;i++)
 xor=xor^i;
xor=xor & -xor  //Isolate the last digit

for(i = 0; i < n; i++)
{
if(arr[i] & xor)
  x = x ^ arr[i]; 
else
  y = y ^ arr[i]; 
}
for(i = 1; i <= n-3; i++)
{
if(i & xor)
  x = x ^ i; 
else
  y = y ^ i;