数组存放1-n,在数组中存在一个重复的数,找出这个重复的数
目录
方法一:
数组中的数据是从1-n,对数据求和,再减去数组中数据元素之和,就是重复的数
int FindDublicate(int* nums, int n)
{
assert(nums != NULL);
int sum = 0;
for (int i = 0; i < n; i++)
{
sum += nums[i];
}
return sum - (n*(n - 1) / 2);
}
缺点:求和数据太大,会超出整型的范围((2^31)-1)
方法二:
从一下标开始依次进行比较,看后续有没有和一下标存储的数据相同的
int FindDublicate2(int* nums, int n)
{
assert(nums != NULL);
for (int i = 0; i < n; i++)
{
for (int j = i + 1; j < n; j++)
{
if (nums[i] == nums[j])
{
return nums[i];
}
}
}
}
方法三:
先对数组元素进行排序,然后再对相邻元素进行比较,相同则返回数组下标
//排序
void paixu(int* nums, int n)
{
assert(nums != NULL);
for (int i = 0; i < n-1; i++)
{
for (int j = i + 1; j < n; j++)
{
if (nums[i] > nums[j])
{
int tmp = nums[i];
nums[i] = nums[j];
nums[j] = tmp;
}
}
}
}
//先排序。再两两比较
int FindDublicate3(int* nums, int n)
{
assert(nums != NULL);
paixu(nums, n);
int tmp = -1;
//qsort(nums, n, sizeof(int),Compare_ints);
for (int i = 0; i < n-1; i++)
{
if (nums[i] = nums[i + 1])
{
tmp = nums[i];
break;
}
}
return tmp;
}
方法四:
查表
将数组原有的数据当成新开辟的空间的下标,依次对原来数据的下标元素进行操作,将下标所对应的数据从0置为1的,二次出现,置为0
int FindDublicate4(int* nums, int n)
{
assert(nums != NULL);
int* index = (int*)malloc(sizeof(int) * n);
memset(index, 0, sizeof(int) * n);
int idx = 0;
for (int i = 0; i < n; i++)
{
idx = nums[i];
if (index[idx] == 0)
{
index[idx] += 1;
}
else
break;
}
free(index);
index = NULL;
return idx;
}
方法五
快慢指针
(1)从第一个下标的开始,将下标所存的内容作为新的下标进行查找
(2)快指针一定会提前进入循环,慢指针一定可以追上快指针
(3)将慢指针置为0,快指针在相遇的地方,快指针和慢指针同时加1,直到两个指针相遇,相遇的地方就是,数组中重复的数
int FindDublicate5(int* nums, int n)
{
assert(nums != NULL);
int fast=0;
int slow=0;
do
{
slow = nums[slow];
fast = nums[fast];
fast = nums[fast];
} while (slow != fast);
slow = 0;
while (slow != fast)
{
slow = nums[slow];
fast = nums[fast];
}
return slow;
}