数组中重复的数字03---剑指offer

一本好书,书已看完(作者已提供所有习题编程源码),不多说。现在第二遍准备慢慢刷题来提高编码实践能力。先从简单入手!虽然是一个简单的题目,但是知易行难!(虽然看过书,但是自己实现的时候对数组元素的合法性检查就没有考虑到)

题目:找出数组中重复的数字

在一个长度为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;
}

运行结果:

原书的作者测试代码考虑的非常全面!这里主要是重在算法实现,原书作者的代码更具有学习参考价值!这里就当学习笔记!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值