标签:memset pos cpp 不用 res false span class int
题目:
数组a[N],1至N-1这N-1个数存放在a[N]中,其中某个数重复一次。写一个函数,找出被重复的数字。
方法一:异或法。
数组a[N]中的N个数异或结果与1至N-1异或的结果再做异或,得到的值即为所求。
代码:
#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;
}
方法二:数学法。
对数组的所有项求和,减去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\n",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\n",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\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。原数组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\n",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\n",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‘ == 0
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]);
}
标签:memset pos cpp 不用 res false span class int
原文地址:http://www.cnblogs.com/pandang/p/7359559.html