第四十九题:数组中重复的数字

题目

在一个长度为n的数组里的所有数字都在 0 到 n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。

举例说明

例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是重复的数字 2 或者 3。

题目分析

思路一:

解决这个问题的一个简单的方法是先把输入的数组排序。从排序的数组中找出重复的数字时间很容易的事情,只需要从头到尾扫描排序后的数组就可以了。排序一个长度为 n 的数组需要 O(nlogn)的时间。

思路二:

还可以利用哈希表来解决这个问题。从头到尾按顺序扫描数组的每个数,每扫描一个数字的时候,都可以用 O(1)的时间来判断哈希表里是否已经包含了该数字。如果哈希表里还没有这个数字,就把它加入到哈希表里。如果哈希表里已经存在该数字了,那么就找到一个重复的数字。这个算法的时间复杂度是 O(n),但它提高时间效率是以一个大小为 O(n)的哈希表为代价的。我们再看看有没有空间复杂度为 O(1)的算法。

/*
	1. 遍历数组,采用hashmap存放每个元素,其中元素作为key存储,value为0。 
	2. 当前遍历元素插入hashmap时,先检查hashmap中是否已经存在同样的key。 
	3. 若存在,记录下该值,返回true;若不存在,存入map中,继续遍历,直到数组结束,返回false.
*/
	public boolean duplicate(int numbers[],int length,int [] duplication) {
	        boolean flag = false;
	        if(numbers==null || length==0){
	            return flag;
	        }
	        HashMap<Integer, Integer> map = new HashMap<Integer, Integer>();
	        for(int num: numbers){
	            if(map.containsKey(num)){
	                flag = true;
	                duplication[0] = num;
	                break;
	            }
	            map.put(num, 0);
	        }
	        return flag;
	    }

根据题目描述,数组里面的值范围在0~n-1,我们可以利用布尔型的辅助数组实现数组元素查重。利用数组的值作为辅助数组的下标,当数组中存在重复的数字时,那它们就指向了同一个以该值为下标的辅助数组元素。利用这一点,在遍历访问数组的时候,每访问一个元素,将该元素值作为辅助数组元素下标,并将该辅助数组元素设置为true。当首次遍历到辅助数组元素为true的时候即找到第一个重复出现的数字。

package com.newcoder.offer;

public class Test {

	public static void main(String[] args) {
		int[] numbers1 = { 2, 1, 3, 1, 4 };
		System.out.println(duplicate(numbers1));
		int[] numbers2 = { 2, 4, 3, 1, 4 };
		System.out.println(duplicate(numbers2));
		int[] numbers3 = { 2, 4, 2, 1, 4 };
		System.out.println(duplicate(numbers3));
		int[] numbers4 = {};
		System.out.println(duplicate(numbers4));
		int[] numbers5 = { 2, 1, 3, 5, 4 };
		System.out.println(duplicate(numbers5));
	}

	public static boolean duplicate(int numbers[]) {
		boolean[] assist = new boolean[numbers.length];
		int dulpNum = 0;
		for (int i = 0; i < assist.length; i++) {
			if (assist[numbers[i]] == true) {
				dulpNum = numbers[i];
				return true;
			}
			assist[numbers[i]] = true;
		}
		return false;
	}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值