面试题3:数组中重复的数字

本文介绍了几种寻找数组中重复数字的算法,包括使用额外数组、原地交换元素和二分查找的方法,适用于不同条件下的重复数字查找。

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

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

思路一:利用hash表,新建一个相同长度的数组,遍历原数组,每遍历一个元素,判断新数组中对应的下标(例如元素为2,对应下标就为2)是否含有该元素,如果没有,新数组对应的下标存储该元素,如果已经含有该元素,说明该元素重复,输出。

解法一:(时间复杂度为O(n),空间复杂度为O(n))

public class Test1 {
	public static void main(String[] args) {
//		int[] a={2,3,1,0,4,5,6};
//		int[] a={2,3,1,0,4,5,3};
//		int[] a={2,3,1,0,2,5,3};
//		int[] a={2,3,10,0,2,5,3};
		int[] a =null;
		int index=findChongfu(a);
		if(index==-2){
			System.out.println("数组不正常");
		}else if(index==-1){
			System.out.println("数组中没有重复元素");
		}else{
			System.out.println("数组中一个重复元素为:"+index);
		}
	}
	private static int findChongfu(int[] a) {
		if(a==null||a.length<=0){
			return -2;
		}
		int length=a.length;
		for(int i=0;i<length;i++){//判断非法元素
			if(a[i]<0||a[i]>length-1){
				return -2;
			}
		}
		int[] b=new int[length];
		for(int i=0;i<length;i++){
			b[i]=-1;
		}
		for(int i=0;i<length;i++){
			if(a[i]!=b[a[i]]){
				b[a[i]]=a[i];
			}else{
				return a[i];
			}
		}
		return -1;
	}
}

 

思路二:遍历数组,从下标0开始,如果下标为0的元素i也为0,就遍历下标1,元素i不为0,就判断元素i和下标为i的元素j相不相等,相等说明为重复元素,输出,不相等就交换两个元素,此时下标0的元素为j,再重复判断,直到发现重复数字。

解法二:(时间复杂度为O(n),空间复杂度为O(1))

public class Test2 {
	public static void main(String[] args) {
		int[] a={2,3,1,0,4,5,6};
//		int[] a={2,3,1,0,4,5,3};
//		int[] a={2,3,1,0,2,5,3};
//		int[] a={2,3,10,0,2,5,3};
//		int[] a =null;
		int index=findChongfu(a);
		if(index==-2){
			System.out.println("数组不正常");
		}else if(index==-1){
			System.out.println("数组中没有重复元素");
		}else{
			System.out.println("数组中一个重复元素为:"+index);
		}
	}
	private static int findChongfu(int[] a) {
		if(a==null||a.length<=0){
			return -2;
		}
		int length=a.length;
		for(int i=0;i<length;i++){//判断非法元素
			if(a[i]<0||a[i]>length-1){
				return -2;
			}
		}
		for(int i=0;i<length;i++){
			while(a[i]!=i){
				if(a[i]==a[a[i]]){
					return a[i];
				}else{
					int temp=a[i];
					a[i]=a[temp];
					a[temp]=temp;
				}
			}
		}
		return -1;
	}
}

题目二:不修改数组找出重复的数字

在一个长度为n+1的数组里的所有数字都在1~n的范围内,所有数组中至少有一个数字是重复的,请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,如果输入长度为8的数组{2,3,5,4,3,2,6,7},那么对应输出是重复的数字2或者3。

思路:因为在1~n的范围中有n+1个数,所以肯定存在重复数字,加入把数组分成两部分,如题目中的数组长度为8,分成1~4和5~7,那么如果没有重复的话,则1~4中少于4个数,5~7中少于3个数,反之,如果数组中在1~4范围内的数字超过4个,则1~4中肯定至少有个重复数字,再将1~4分成1~2和2~3,以此类推。

解法:(时间复杂度为O(nlogn),空间复杂度为O(1))

public class Test3 {
	public static void main(String[] args) {
//		int a[]={2,3,5,4,3,2,6,10};
//		int a[]=null;
//		int a[]={2,3,5,4,3,2,6,7};
		int a[]={2,1,5,3,3,2,6,7};
		int index=findChongfu(a);
		if(index==-2){
			System.out.println("数组不正常");
		}else if(index==-1){
			System.out.println("数组中没有重复元素");
		}else{
			System.out.println("数组中的一个重复元素为:"+index);
		}
	}

	private static int findChongfu(int[] a) {
		if(a==null||a.length<=0){
			return -2;
		}
		int length=a.length;
		for(int i=0;i<length;i++){
			if(a[i]<1||a[i]>length-1){
				return -2;
			}
		}
		int end=length-1;
		int start=1;
		while(end>=start){
			int middle=(end-start)/2+start;
			int count=findCount(a,start,middle);
			if(end==start){
				if(count>1){
					return start;
				}else{
					break;
				}
			}
			if(count>(middle-start+1)){
				end=middle;
			}else{
				start=middle+1;
			}
		}
		return -1;
	}

	private static int findCount(int[] a, int start, int end) {
		if(a==null||a.length<=0){
			return 0;
		}
		int count=0;
		for(int i=0;i<a.length;i++){
			if(a[i]>=start&&a[i]<=end){
				count++;
			}
		}
		return count;
	}
}

 

此刻的努力是为了明天的放松。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值