題目:
數(shù)組a[N],1至N-1這N-1個數(shù)存放在a[N]中,其中某個數(shù)重復(fù)一次。寫一個函數(shù),找出被重復(fù)的數(shù)字。
方法一:異或法。
數(shù)組a[N]中的N個數(shù)異或結(jié)果與1至N-1異或的結(jié)果再做異或,得到的值即為所求。
代碼:
- #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\n",result);
-
- }
-
-
-
- int main(int argc, char* argv[])
- {
- int a[] = {1,2,1,3,4};
- xor_findDup(a,5);
- return 0;
- }
方法二:數(shù)學(xué)法。
對數(shù)組的所有項求和,減去1至N-1的和,即為所求數(shù)。
- #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\n",result);
-
- }
-
-
-
- int main(int argc, char* argv[])
- {
- int a[] = {1,2,4,3,4};
- xor_findDup(a,5);
- return 0;
- }
對于求和,可以直接根據(jù)公式定義一個宏。#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));
- int tmp2 = 0;
-
- for (int i=0; i<N; ++i)
- {
- tmp2+=a[i];
- }
- int result=tmp2-tmp1;
- printf("%d\n",result);
- }
-
- int main(int argc, char* argv[])
- {
- int a[] = {1,2,4,2,3};
- xor_findDup(a,5);
- return 0;
- }
方法三:標(biāo)志數(shù)組法
申請一個長度為n-1且均為'0'組成的字符串。然后從頭遍歷a[n]數(shù)組,取每個數(shù)組元素a[i]的值,將其對應(yīng)的字符串中的相應(yīng)位置置1,如果已經(jīng)置過1的話,那么該數(shù)就是重復(fù)的數(shù)。就是用位圖來實(shí)現(xiàn)的。 如果考慮空間復(fù)雜度的話,其空間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\n",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。原數(shù)組a[i]最大是N-1,若a[i]=K在某處出現(xiàn)后,將a[K]加一次N,做標(biāo)記,當(dāng)某處a[i]=K再次成立時,查看a[K]即可知道K已經(jīng)出現(xiàn)過。該方法不用另外開辟O(N)的內(nèi)存空間,但是在查重之后要將數(shù)組進(jìn)行恢復(fù)。
- #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("有重復(fù) %d\n",temp);
- return;
- }
- }
-
- printf("無重復(fù)");
- 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;
- }
方法五:符號標(biāo)志法
上個方法出現(xiàn)后是加N,也可以出現(xiàn)后加個負(fù)號,就是符號標(biāo)志法。
- #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("有重復(fù) %d\n",temp);
- return;
- }
- }
- printf("無重復(fù)");
- 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;
- }
以上的方法對數(shù)組元素的值的范圍是有限制的,如果數(shù)組元素的值不是在1至N-1范圍時,可以先求出數(shù)組元素的最大值。
- #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 );
- for(i=0; i<n; i++)
- {
- if(arrayflag[arr[i]] == '\0')
- 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\n",myArry[prePos]);
- }
-
轉(zhuǎn):http://buptdtt.blog.51cto.com/2369962/749049
posted on 2014-03-27 19:40
fly 閱讀(535)
評論(0) 編輯 收藏 所屬分類:
算法