题目:假设数组 array 有 n 个元素,元素取值范围是 1~n,如何判定数组是否存在重复元素?
方法一:对数组进行排序(可以用效率比较高的排序算法,如快速排序、堆排序等),然后比较相邻的元素是否相同。时间复杂度为 O(nlogn),空间复杂度为O(1)。下面借助c语言类库中自带的快速排序算法qsort,来实现排序。
#include <iostream>
int comp(const void *a, const void *b) // 注意const
{
return *(int *)a - *(int *)b; // 升序
}
bool IsArrayRepeat(int *arr, int len)
{
if (!arr || len <= 1)
return false;
qsort(arr, len, sizeof(int), comp);
for (int i = 0; i < len - 1; i++)
{
if (arr[i] == arr[i + 1])
return true;
}
return false;
}
int main(int argc, const char * argv[]) {
int arr[7] = {1,2,3,4,5,6,2};
int len = sizeof(arr)/sizeof(int);
if (IsArrayRepeat(arr, len))
printf("数组中存在重复元素\n");
else
printf("数组中不存在重复元素\n");
return 0;
}
备注:上述程序的运行环境为:Xcode。
(1)qsort 是 C 标准库函数,包含在头文件 stdlib.h 中。
在 ISO C++中为 std::qsort,包含在文件 cstdlib 中。#include<cstdlib>
之后,可以直接调用 std::qsort 或 using namespace std;然后再调用 qsort。
(2)sort( )和qsort( )知识点补充: C++ 排序函数 sort(),qsort()的用法
方法二:Hash法 或者 位图法,时间复杂度 和 空间复杂度 都是 O(n)。
方法三:由于本题中数组array有 n 个元素,而且元素的取值范围是 1~ n,所以可以通过遍历数组,假设下标 i 位的数字为 j。那么通过交换,将“下标 i 位上的数字 j“ 交换到“下标 j - 1 位上“,直到所有数字都出现在自己对应的下标处,或发生了冲突。此算法的时间复杂度为O(n),空间复杂度为O(1)。
#include <iostream>
bool IsArrayRepeat2(int arr[], int len)
{
if (!arr || len <= 1)
return false;
for (int i = 0; i < len; i++)
{
if (arr[i] <= 0 || arr[i] > len)
return false;
}
int j = -1;
for (int i = 0; i < len; i++)
{
j = arr[i];
if (i == j - 1)
continue;
if (arr[i] == arr[j - 1])
return true;
arr[i] = arr[j - 1];
arr[j - 1] = j;
i--;
}
return false;
}
int main(int argc, const char * argv[]) {
int arr[7] = {7,1,3,4,7,6,2};
int len = sizeof(arr)/sizeof(int);
if (IsArrayRepeat2(arr, len))
printf("数组中存在重复元素\n");
else
printf("数组中不存在重复元素\n");
return 0;
}
补充一个注意点,关于数组越界的问题(上述代码的运行环境,均为Xcode):
bool IsArrayRepeat2(int arr[], int len) // 主要针对IsArrayRepeat2做一些说明
{
if (!arr || len <= 1)
return false;
// 如果把IsArrayRepeat2中的这段代码注释掉,那么当原arr[7]数组中出现0、-1、8等数字时,虽然会造成arr[j-1]越界,但是程序仍然能正常运行,没有报错。但是输出是错误的,数组越界时访问到的数值会给输出带来异常,所以加上这段代码很有必要。
// for (int i = 0; i < len; i++)
// {
// if (arr[i] <= 0 || arr[i] > len)
// return false;
// }
int j = -1;
for (int i = 0; i < len; i++)
{
j = arr[i];
if (i == j - 1)
continue;
if (arr[i] == arr[j - 1])
return true;
arr[i] = arr[j - 1];
arr[j - 1] = j;
i--;
}
return false;
}