zoukankan      html  css  js  c++  java
  • 找出数组中唯一重复的数(转)

    题目:

    数组a[N],1至N-1这N-1个数存放在a[N]中,其中某个数重复一次。写一个函数,找出被重复的数字。

    方法一:异或法。

    数组a[N]中的N个数异或结果与1至N-1异或的结果再做异或,得到的值即为所求。

    • 设重复数为A,其余N-2个数异或结果为B。 
    • N个数异或结果为A^A^B 
    • 1至N-1异或结果为A^B 
    • 由于异或满足交换律和结合律,且X^X = 0  0^X = X; 
    • 则有 
    • (A^B)^(A^A^B)=A^B^B=A 

    代码:

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <math.h>  
    #include<time.h>  
    void xor_findDup(int * a,int N)    
    {    
        int i;    
        int result=0;    
        for(i=0;i<N;i++)    
        {    
            result ^= a[i];    
        }    
          
        for (i=1;i<N;i++)     
        {    
            result ^= i;    
        }    
          
        printf("%d
    ",result);    
          
    }    
     
     
     
    int main(int argc, char* argv[])    
    {    
        int a[] = {1,2,1,3,4};    
        xor_findDup(a,5);    
        return 0;    
    }   
    

      

     方法二:数学法。

    对数组的所有项求和,减去1至N-1的和,即为所求数。

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <math.h>  
    #include<time.h>  
    void xor_findDup(int * a,int N)    
    {    
        int tmp1 = 0;  
          
        int tmp2 = 0;  
          
        for (int i=0; i<N-1; ++i)  
              
        {  
              
            tmp1+=(i+1);  
              
            tmp2+=a[i];  
              
        }  
        tmp2+=a[N-1];  
        int result=tmp2-tmp1;     
        printf("%d
    ",result);    
          
    }    
     
     
     
    int main(int argc, char* argv[])    
    {    
        int a[] = {1,2,4,3,4};    
        xor_findDup(a,5);    
        return 0;    
    }   
    

      

    对于求和,可以直接根据公式定义一个宏。#define sum(x)  (x*(x+1)/2) 
     

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <math.h>  
    #include<time.h>  
    #define sum(x)  (x*(x+1)/2)   
    void xor_findDup(int * a,int N)    
    {    
        int tmp1 = sum((N-1));//注意N-1要加括号     
        int tmp2 = 0;  
          
        for (int i=0; i<N; ++i)       
        {             
            tmp2+=a[i];   
        }  
        int result=tmp2-tmp1;     
        printf("%d
    ",result);        
    }    
     
    int main(int argc, char* argv[])    
    {    
        int a[] = {1,2,4,2,3};    
        xor_findDup(a,5);    
        return 0;    
    }   
    

      

     方法三:标志数组法

    申请一个长度为n-1且均为'0'组成的字符串。然后从头遍历a[n]数组,取每个数组元素a[i]的值,将其对应的字符串中的相应位置置1,如果已经置过1的话,那么该数就是重复的数。就是用位图来实现的。 如果考虑空间复杂度的话,其空间O(N)

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <math.h>  
    #include<time.h>  
    #define sum(x)  (x*(x+1)/2)   
    void xor_findDup(int * arr,int NUM)    
    {    
        int *arrayflag = (int *)malloc(NUM*sizeof(int));      
        int i=1;  
          
        while(i<NUM)  
        {  
            arrayflag[i] = false;  
            i++;  
        }     
          
        for( i=0; i<NUM; i++)         
        {         
            if(arrayflag[arr[i]] == false)            
                arrayflag[arr[i]] = true;          // 置出现标志  
              
            else      
            {   
                printf("%d
    ",arr[i]);  
                return ; //返回已经出现的值  
            }  
              
         }    
    }    
     
    int main(int argc, char* argv[])    
    {    
        int a[] = {1,3,2,4,3};    
        xor_findDup(a,5);    
        return 0;    
    }    
    

      

     方法四:固定偏移量法

    a[N],里面是1至N-1。原数组a[i]最大是N-1,若a[i]=K在某处出现后,将a[K]加一次N,做标记,当某处a[i]=K再次成立时,查看a[K]即可知道K已经出现过。该方法不用另外开辟O(N)的内存空间,但是在查重之后要将数组进行恢复。

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <math.h>  
    #include<time.h>  
    void xor_findDup(int * arr,int NUM)    
    {    
        int temp=0;       
        for(int i=0; i<NUM; i++)          
        {  
              
            if(arr[i]>=NUM)           
                temp=arr[i]-NUM;            // 该值重复了,因为曾经加过一次了        
            else              
                temp=arr[i];          
                      
            if(arr[temp]<NUM)         
            {         
                arr[temp]+=NUM; //做上标记            
            }  
              
            else              
            {             
                printf("有重复 %d
    ",temp);              
                return;           
            }         
        }  
                  
        printf("无重复");  
        return ;   
    }    
    void clear(int *data,int num)//清理数据  
    {  
        for(int i=0;i<num;i++)  
        {  
            if(data[i]>num)  
                data[i]-=num;  
        }  
     
    }  
    int main(int argc, char* argv[])    
    {    
        int a[] = {2,4,3,4,1};    
        xor_findDup(a,5);    
        clear(a,5);  
        return 0;    
    }    
    

      

     方法五:符号标志法

    上个方法出现后是加N,也可以出现后加个负号,就是符号标志法。

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <string.h>  
    #include <math.h>  
    #include<time.h>  
     
    void xor_findDup(int * arr,int NUM)    
    {         
        int temp=0;          
        for(int i=0; i<NUM; i++)        
        {                    
            if(arr[i]<0)     
                temp=0-arr[i];  // 该值重复了,因为曾经加过一次了     
            else                           
                temp=arr[i];                
            if(arr[temp]>0)             
            {                    
                arr[temp]=0-arr[temp]; //做上标记        
            }                
            else              
            {               
                printf("有重复 %d
    ",temp);      
                return;               
            }            
        }                
        printf("无重复");    
        return ;    
     }     
     void clear(int *data,int num)//清理数据  
     {     
         for(int i=0;i<num;i++)     
         {        
             if(data[i]<0)           
                 data[i]=0-data[i];     
       }     
    }    
     int main(int argc, char* argv[])    
     {        
         int a[] = {3,2,1,4,1};       
         xor_findDup(a,5);     
         clear(a,5);      
         return 0;    
     }      
    

      

    以上的方法对数组元素的值的范围是有限制的,如果数组元素的值不是在1至N-1范围时,可以先求出数组元素的最大值。

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <string.h>  
    #include <math.h>  
    #include<time.h>  
     
    int  do_dup_mal(int arr[], int n, int *pre, int *back)  
    {  
        int MAX = -1;  
        int i = 0;  
        int sameVal = -1;  
        *pre = *back = -1;  
          
        for (int j=0; j<n; j++)  
        {  
            if (arr[j] > MAX) MAX = arr[j];//找出数组中的最大数  
        }  
          
        char *arrayflag = new char[MAX+1] ;  
        if (NULL == arrayflag)  
            return -1;  
        memset(arrayflag, 0, MAX+1 ); // '' == 0  
        for(i=0; i<n; i++)  
        {  
            if(arrayflag[arr[i]] == '')  
                arrayflag[arr[i]] = '1'; // 置出现标志  
            else 
            {  
                sameVal = arr[i]; //返回已经出现的值  
                *back = i;  
                break;  
            }  
        }  
        delete[] arrayflag;  
        if (i < n)  
        {  
            for (int j=0; j<n; j++)  
            {  
                if (sameVal == arr[j])  
                {  
                    *pre = j;  
                    return true;  
                }  
            }  
        }  
        return false;  
    }  
     
     
     
     
     
    void main(int argc, char *argv[])  
    {  
        int prePos = -1, backPos = -1;  
        int myArry[11];  
        myArry[0] = 1;  
        myArry[1] = 3;  
        myArry[2] = 3;  
        myArry[3] = 4;  
        myArry[4] = 5;  
        myArry[5] = 22;  
        myArry[6] = 7;  
        myArry[7] = 13;  
        myArry[8] = 9;  
        myArry[9] = 2;  
        myArry[10] = 12;  
          
          
        if (do_dup_mal(myArry, 11, &prePos, &backPos) )  
            printf("%d
    ",myArry[prePos]);  
    }  
         
    

      

  • 相关阅读:
    mac上python3安装HTMLTestRunner
    双目深度估计传统算法流程及OpenCV的编译注意事项
    深度学习梯度反向传播出现Nan值的原因归类
    1394. Find Lucky Integer in an Array
    1399. Count Largest Group
    1200. Minimum Absolute Difference
    999. Available Captures for Rook
    509. Fibonacci Number
    1160. Find Words That Can Be Formed by Characters
    1122. Relative Sort Array
  • 原文地址:https://www.cnblogs.com/pandang/p/7359559.html
Copyright © 2011-2022 走看看