取值为[1,n-1]含n个元素的整数数组至少存在一个重复数,找出一个重复元素

1. 问题描述

取值为[1,n-1]含n个元素的整数数组至少存在一个重复数,O(n)时间内找出其中任意一个重复数。如a[]={1,2,2,4,5,4},则2和4均是重复元素。


2. 解决方案

<单链表存在环> 第三种解决方案有很强的技巧性。“判断单链表是否存在环”是一个非常经典的问题,同时单链表可以采用数组实现,此时每个元素值作为next指针指向下一个元素。该题可以转化为“已知一个单链表中存在环,找出环的入口点”。

该题思路如下:将a[i]看做第i个元素的索引,即:a[i]->a[a[i]]->a[a[a[i]]]->a[a[a[a[i]]]]->….最终形成一个单链表,由于数组a中存在重复元素,则一定存在一个环,且环的入口元素即为重复元素。

该题的关键在于,数组a的大小时n,而元素的范围是[1,n-1],所以a[0]不会指向自己,进而不会陷入错误的自循环。如果元素的范围中包含0,则该题不可直接采用该方法。

代码如下:

int find_duplicated_integer2(int a[], int n) {
	int x, y;
	x = y = 0;
	do {
		x = a[a[x]]; //x一次走两步
		y = a[y]; //y一次走一步
	} while(x != y); //找到环中的一个点
	x = 0;
	do {
		x = a[x];
		y = a[y];
	} while(x != y); //找到入口点
	return x;
}


以上参见http://www.jobcoding.com/datastructure-and-algorithm/array/one-unsorted-array/find-one-duplicated-integer/



一开始不明白为什么分这样的两趟进行,后来用数学式推导了一下是对的。

证明上述方法的正确性:

设环外、环上元素个数分别为a,b。

进行第一次循环,初始状态x=0,y=0。x,y从环外开始走,第a+1步进入环后必定在环上追赶而相遇,设相遇时y走了a+m步,则x走了2(a+m)步=a+(a+2m).

a+m,a+(a+2m)在环上同一位置(但并不一定是环的入口a+1),那么两者之差a+m是环上元素个数b的倍数,即a+m可被b整除,设a+m=nb.

进行第二次循环,初始状态x=0,y=a+m。x从环外开始走,第a+1步到达环的入口;此时y到达a+m + a+1=a+nb+1,同样也是环的入口。故两者在环的入口相遇。

入口点元素即为数组重复元素。


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值