剑指offer--51.数组中重复的数字

本文介绍了一种在数组中查找重复数字的有效算法。通过排序、哈希表和原地置换三种方法,实现时间复杂度从O(nlogn)到O(n)的优化,同时考虑空间复杂度。展示了具体的Java代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:在一个长度为n的数组里所有的数字都是在0到n-1范围,数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次,请找出数组中任意一个重复的数字,eg,输入长度为7的数组a={2,3,1,0,2,5,3},那么对应的输出是重复的数字2或者3

分析:可考虑几种方法

1.先把输入的数组排序,从排序的数组中找出重复的数字,即从头到尾扫描排序后的数组,排序长为n的数组的时间复杂度为O(nlogn)

2.哈希表,从头到尾顺序扫描数组的每个数,每扫描到一个数字的时候,都可以用O(1)的时间判断哈希表里是否已经包含了该数字,如果哈希表里还没有该数字,就把它加入哈希表,如果有则找到一个重复数字,时间复杂度为O(n),但是以O(n)的空间作为代价

3.从头到尾扫描数组中的数字,当扫描到下标为i的数字时,首先比较这个数字(m)是否等于i,如果是,接着扫描下一个数字,如果不是,再拿它和第m个数字进行比较,如果它和第m个数字相等,就找到了一个重复的数字(该数字在下标为i和m的位置都出现了),如果它和第m个数字不相等,就把第i个数字和第m个数字交换,把m放到属于它的位置,接着重复比较、交换过程。时间复杂度为O(n),空间为O(1)

import java.util.*;

public class wr51duplicate {
	public static int duplicate(int numbers[],int length){
		if(numbers==null || numbers.length==0){
			return -1;
		}
		Arrays.sort(numbers);
		int flag=0;
		int duplication=0;
		for(int i=0;i<length-1;i++){
			if(numbers[i]==numbers[i+1]){
				duplication=numbers[i];
				flag=1;
				break;
			}
		}
		return duplication;
	}
	
	public static int duplicate2(int numbers[],int length){
		if(numbers==null || numbers.length==0){
			return -1;
		}
		HashSet<Integer> hs=new HashSet<>();
		int duplication=0;
		for(int i=0;i<length;i++){
			if(!hs.add(numbers[i])){
				duplication=numbers[i];
				break;
			}
		}
		return duplication;
	}
	
	public static boolean duplicate(int numbers[],int length,int [] duplication){
		if(numbers==null || numbers.length==0){
			return false;
		}
		for(int i=0;i<length;i++){
			while(numbers[i]!=i){
				if(numbers[i]==numbers[numbers[i]]){
					duplication[0]=numbers[i];
					return true;
				}
			    int temp=numbers[i];
			    numbers[i]=numbers[temp];
			    numbers[temp]=temp;
			}
		}
		return false;
	}

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int []a={2,3,1,0,2,5,3};
		int []result=new int[1];
		System.out.println(duplicate(a,a.length));
		System.out.println(duplicate2(a,a.length));
		System.out.println(duplicate(a,a.length,result));
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值