【题3数组中重复的数字】Java实现

【题3数组中重复的数字】
【题目1】
在一个长度为n的数组里的所有数字都在0-n-1的范围内,数组中某些数字是重复的,但不知道每个数字重复了几次,请找出数组中任意一个重复的数字,例如,如果输入长度为7的数组,{2,3,1,0,2,5,3},那么对应的输出是2或者3
【方法】
1.
(1)先把输入数组排序
(2)从头到尾扫描排序后的数组
(3)排一个长度为n的数组需要O(nlogn)
2哈希表
(1) 从头到尾按顺序扫描数组的每个数字
(2) 每扫描一个用O(1)时间判断哈希表里是否已经包含该数字
(3) 若包含则一个重复数字,若不包含则插入到哈希表
3数字都在0~n-1范围内排序之后,i将对应下标i的位置
重排数组
(1)扫描到下标i的数字时,比较这个数字(m)是否=i
(2)若等于,扫描下一个。不等则与第m个数字比较
(3)如果与第m个数字相等,则 有一个重复数字
(4)把第i个数字与第m个数字交换,把m放到属于他的位置
在这里插入图片描述
实现

package ti3;
/**
*
* 题目:在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,
* 也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。例如,如果输入长度为7的数组{2, 3, 1, 0, 2, 5, 3},
* 那么对应的输出是重复的数字2或者3。
* test1:数组输入无效!
test2:数组中无重复数字!
test3:数字大小超出范围!
test4:重复数字为:2
*/
public class FindDuplication {
	/**
	 * 找到数组中一个重复的数字
	 * 返回-1代表无重复数字或者输入无效
	 */
	public int getDuplicate(int[] arr){
		if(arr == null || arr.length <= 0){
			System.out.println("数组输入无效");
			return -1;
		}
		for(int a:arr){
			if(a < 0 || a > arr.length - 1){
				System.out.println("数字大小超出范围");
				return -1;
			}
		}
		for(int i = 0;i < arr.length;i++){
			int temp;
			while(arr[i] != i){
				if(arr[arr[i]] == arr[i]){
					return arr[i];
				}
				//交换arr[arr[i]]和arr[i]
				temp = arr[i];
				arr[i] = arr[temp];
				arr[temp] = temp;
			}
		}
		System.out.println("数组中无重复的数字");
		return -1;
	}
	//测试代码
	//数组为null
	public  void test1()
	{
		System.out.println("test1");
		int[] a = null;
		int  dup = getDuplicate(a);
		if(dup >= 0){
			System.out.println("重复数字为"+dup);
		}
	}
	//数组无重复数字
	public  void test2()
	{
		System.out.println("test2");
		int[] a = {0,1,2,3};
		int  dup = getDuplicate(a);
		if(dup >= 0){
			System.out.println("重复数字为"+dup);
		}
	}
	//数组数字越界
	public  void test3()
	{
		System.out.println("test3");
		int[] a = {1,2,3,4};
		int  dup = getDuplicate(a);
		if(dup >= 0){
			System.out.println("重复数字为"+dup);
		}
	}
	//重复数字为2
	public  void test4()
	{
		System.out.println("test4");
		int[] a = {1,2,3,2,4};
		int  dup = getDuplicate(a);
		if(dup >= 0){
			System.out.println("重复数字为"+dup);
		}
	}
	public static void main(String[] args) {
		FindDuplication f = new FindDuplication();
		f.test1();
		f.test2();
		f.test3();
		f.test4();
	}
}

【题目2不修改数组找出重复的数字】
在一个长度尾n+1的数组里的所有数字都在1~n的范围内,所有数组中至少有一个数字时重复的。请找出数组中任意一个重复的数字,但不能修改输入的数组。例如,输入长度为8的数组{2,3,5,4,3,2,6},那么对应 的输出是重复的数字2或3
注意:不能修改原数组
方法:
1.
(1)创建一个长度为n+1的辅助数组,逐一把原数组的每个数字复制到辅助数组
(2)若原数组中被复制的数字为m,则复制到辅助数组下标为m的位置
2.
(1)把从1~n数字从 中间的数字m分为2部分,1-m,m+1~n
(2)如果1~m数字的数目超过了m则这个一半包含重复的数字
否则,另一半m+1~n区间里一定包含重复的数字
(3)继续一分为二
在这里插入图片描述

实现

package ti3;

public class DuplicationInArrayNotEdit {
	private int countRange(int[] array,int length,int start,int end){
		if(start < 0 ||end > length-1)throw new IllegalArgumentException("Wrong Arguments");
		int count = 0;
		for(int i = 0;i<length;++i){
			if(array[i]<=end && array[i]>= start)++count;
		}
		return count;
	}
	public int returnOneDuplication(int[] array){
		if(array == null) throw new IllegalArgumentException("Wrong Arguments");
		int length = array.length;
		int start = 1;
		int end = length - 1;
		while(start <= end){
			int middle = ((end-start)>>1)+start;
			int count = countRange(array,length,start,middle);
			if(start == end){
				if(count >1)return start;
				else break;
			}
			if(count>middle - start+1)end = middle;
			else start = middle +1;//注意这个+1
		}
		return -1;
	}
	public static void main(String[] args) {
		DuplicationInArrayNotEdit duplicationInArrayNotEdit = new DuplicationInArrayNotEdit();
		int[] Array = new int[] {2,3,5,4,3,2,6,7};
		System.out.println(duplicationInArrayNotEdit.returnOneDuplication(Array));
	}
}

参考:
1.《剑指offer》
2.https://www.cnblogs.com/yongh/p/9318604.html
3.https://blog.csdn.net/w13261711130/article/details/79973502

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值