一本好书,书已看完(作者已提供所有习题编程源码),不多说。现在第二遍准备慢慢刷题来提高编码实践能力。先从简单入手!虽然是一个简单的题目,但是知易行难!(虽然看过书,但是自己实现的时候对数组元素的合法性检查就没有考虑到)
题目:找出数组中重复的数字。
在一个长度为n的数组里的所有的数字都在0~n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个重复了几次。请找出数组中任意一个重复的数字。例如,如果输出的长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3.
下面的代码目前只是阅读书上的然后自己简单的思考实现一遍。
算法思想:一个数组长度为n,数字都在0~n-1的范围内,不借助外部辅助空间,时间复杂度0(n)。算法本质---就是利用数组下标对数组排序(a[i] = i)(这里本质还是利用数字下标排序,通过比较值和下标,将a[i]放到数组的第i个位置)。 优点: 每个 数字最多只需要交换两次就能找到属于自己的位置。
算法思路:
//从第0个元素开始比较,首先比较元素a[0]与其下标是否相等
//1. 如果相等,下一元素
//2. 如果不相等,
//2.1 先判断a[i] 和 a[a[i]]是否相等,
//2.1.1 如果相等,则该数字就是找到的第一个重复的数字
//2.1.2 如果不相等,则交换a[i] 和 a[a[ai]] 的位置,这样a[i] = i.
//3. 重复步骤1,直到找到了第一个重复的数字
代码实现:
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int duplicate(int Array[], int length, int* value)
{
int i = 0 , j = 0 , temp = 0;
//参数合法性检查
if( (Array == NULL) || (length <= 0 ) )
{
return -1;
}
//数组参数合法性检查 自己实现的时候就没有考虑到这个,虽然看过书了
for(j = 0; j < length; j++)
{
if( (Array[i] < 0) && (Array[i] > length -1) )
return -1;
}
printf(" length = %d\n ",length );
for(i = 0; i < length ; i++ )
{
while(Array[i] != i)
{
if(Array[i] == Array[Array[i]])
{
*value = Array[i];
return 1;
}
temp = Array[i];
Array[i] = Array[temp];
Array[temp] = temp;
}
}
return -1;
}
int main(int argc, char *argv[]) {
int value = -1;
int ret = -1;
int test1[] = {3,1,2,6,2,5,3};
ret = duplicate(test1, sizeof(test1)/sizeof(test1[0]), &value);
if(ret)
printf("duplicate number is %d\n",value);
return 0;
}
运行结果:
原书的作者测试代码考虑的非常全面!这里主要是重在算法实现,原书作者的代码更具有学习参考价值!这里就当学习笔记!