题目:在一个长度为n的数组里的所有数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意重复的数字。例如:如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出的重复的数字2或者3。
分析:数组中的数字都在0~n-1之间,如果没有该数组中没有重复的数字,那么数组重新排序之后数字i出现的位置将是数组下标为i的位置。所有我们对该数组重新排序,从头到尾依次扫描这个数组中的每个数字。假设该数组名为numbers,当扫描到下标为i(numbres[i])比较是不是和i相等。如果是,则接着扫描下一个数字,如果不是,则将下标为numbers[i]的元素和numbers[numbers[i]互换,如果numbers[i]与numbers[numbers[i]]相等,则找到重复的数字。
实现代码:
/*
参数:
number[]:数组
length:长度
value:重复的值
返回值:
true:有重复值
false:无重复值或参数错误
*/
bool selectDuplicate(int numbers[], int length, int* value)
{
//可靠性判断
if (numbers == nullptr || length <= 0)
{
return false;
}
for (int i = 0; i < length; i++)
{
if (numbers[i]<0 || numbers[i] >length - 1)
{
return false;
}
}
for (int i = 0; i < length; i++)
{
while (i != numbers[i])
{
int temp = numbers[i];
if (numbers[temp] == numbers[i])
{
*value = numbers[i];
return true;
}
numbers[i] = numbers[temp];
numbers[temp] = numbers[i];
}
}
return false;
}
测试代码用的是原书中的,附上完整代码:
// ConsoleApplication1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
/*
题目一:找出数组中重复的数字
在一个长度为n的数组里的所有数字都在0~n-1的范围内,数组中的某些数字
是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出
数组中任意一个重复的数字。例如,如果输入长度为7的数组{2,3,1,0,2,5,3},
那么对应的输出是重复的数字2或者3
*/
#include "pch.h"
#include <cstdio>
#include <iostream>
#pragma warning(disable:4996)
using namespace std;
/*
参数:
number[]:数组
length:长度
value:重复的值
返回值:
true:有重复值
false:无重复值或参数错误
*/
bool selectDuplicate(int numbers[], int length, int* value)
{
//可靠性判断
if (numbers == nullptr || length <= 0)
{
return false;
}
for (int i = 0; i < length; i++)
{
if (numbers[i]<0 | numbers[i] >length - 1)
{
return false;
}
}
for (int i = 0; i < length; i++)
{
while (i != numbers[i])
{
int temp = numbers[i];
if (numbers[temp] == numbers[i])
{
*value = numbers[i];
return true;
}
numbers[i] = numbers[temp];
numbers[temp] = numbers[i];
}
}
return false;
}
// ====================测试代码====================
bool contains(int array[], int length, int number)
{
for (int i = 0; i < length; ++i)
{
if (array[i] == number)
return true;
}
return false;
}
void test(const char* testName, int numbers[], int lengthNumbers, int expected[], int expectedExpected, bool validArgument)
{
printf("%s begins: ", testName);
int duplication;
bool validInput = selectDuplicate(numbers, lengthNumbers, &duplication);
if (validArgument == validInput)
{
if (validArgument == false)
{
if (contains(expected, expectedExpected, duplication))
printf("Passed.\n");
else
printf("FAILED.\n");
}
else
printf("Passed.\n");
}
else
printf("FAILED.\n");
}
// 重复的数字是数组中最小的数字
void test1()
{
int numbers[] = { 2, 1, 3, 1, 4 };
int duplications[] = { 1 };
test("Test1", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), true);
}
// 重复的数字是数组中最大的数字
void test2()
{
int numbers[] = { 2, 4, 3, 1, 4 };
int duplications[] = { 4 };
test("Test2", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), true);
}
// 数组中存在多个重复的数字
void test3()
{
int numbers[] = { 2, 4, 2, 1, 4 };
int duplications[] = { 2, 4 };
test("Test3", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), true);
}
// 没有重复的数字
void test4()
{
int numbers[] = { 2, 1, 3, 0, 4 };
int duplications[] = { -1 }; // not in use in the test function
test("Test4", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), false);
}
// 没有重复的数字
void test5()
{
int numbers[] = { 2, 1, 3, 5, 4 };
int duplications[] = { -1 }; // not in use in the test function
test("Test5", numbers, sizeof(numbers) / sizeof(int), duplications, sizeof(duplications) / sizeof(int), false);
}
// 无效的输入
void test6()
{
int* numbers = nullptr;
int duplications[] = { -1 }; // not in use in the test function
test("Test6", numbers, 0, duplications, sizeof(duplications) / sizeof(int), false);
}
int main()
{
test1();
test2();
test3();
test4();
test5();
test6();
return 0;
}