数据结构与算法-剑指Offer系列(2)不修改数组找出重复的数字-Java实现

43 篇文章 0 订阅
40 篇文章 0 订阅

题目2-不修改数组找出重复的数字

描述:

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

思路:

1、使用辅助数组实现上面的功能,但是需要额外的空间O(n),数组下标与数字对应。

2、避免使用O(n)的辅助空间。利用类似二分 查找法将数组分为前后两块,利用长度为8的数组{2,3,5,4,3,2,6,7}为例,长度为8的数字都在1~7的范围内,中间数组4把1~7分成左右两端,左边1~4,右边5~7,然后统计左右两边各自出现的次数,若任一边出现次数大于4则认为有重复。在分别统计各自出现的重复次数。

代码实现:

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

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int[] arr1 = {2, 3, 5, 4, 3, 2, 6, 7};
		int[] arr2 = null;
		int[] arr3 = {2, 3, 5, 4, 8, 1, 6, 7};
		int[] arr4 = {2, 3, 5, 4, 3, 8, 6, 7};
		int result = getDuplicate(arr1);
		System.out.println("重复   "+result);
		result = getDuplicate(arr2); 
		System.out.println("重复   "+result);
		result = getDuplicate(arr3);
		System.out.println("重复   "+result);
		result = getDuplicate(arr4);
		System.out.println("重复   "+result);
	}

	public static int getDuplicate(int[] arr) {
		
		if(arr==null||arr.length<=0) {
			System.out.println("数组为空   ");
			return -1;
		}
		
		for(int a:arr) {
			if(a<1||a>arr.length-1) {
				System.out.println("数组超过规定范围!   ");
				return -1;
			}

		}
		
		int start = 1;
		int len = arr.length;
		int end = len-1;
		while(end>=start) {
			int mid = ((end-start)>>>1)+start;  //使用无符号右移实现除2的效果
			int count = countRange(arr,len,start,mid);
			if(end == start) {
				if(count>1)
					return start;
				else
					break; //出现重复
			}
			
			if(count>(mid-start+1))  //左右出现的次数
				end = mid;
			else
				start = mid+1;
		}
		return -1;
	}
	
	private static int countRange(int[] arr,int len,int left,int right){
		if(arr==null) return 0;
		int count = 0;
		for(int i =0;i<len;i++) {
			if(arr[i]>=left&&arr[i]<=right) {
				++count;
			}
		}
		return count;
	}
}

输出结果:

重复   3
数组为空   
重复   -1
数组超过规定范围!   
重复   -1
数组超过规定范围!   
重复   -1

算法分析:

时间复杂度:O(nlogn) 因为函数中使用while(时间复杂度O(logn)),countRange() 调用O(logn)次,每次O(n)时间

空间复杂度:O(1)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值