剑指Office,编程心得(JAVA / Python)-- 003 数组中重复的数字

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

难度:二星

思路1:时间复杂度O(n)空间复杂度O(1) 

如果数组中没有重复的数组,重排后,则下标index和下标所在的数字应该是相等的,即所有num[index]==index;否则,在数组中必然存在一组数x,y,num[x]=x;num[y]=x。

重排时规则:

扫描整个数组,假设num[i]==i,即这个数在它该有的位置,那么扫描下一个;

如果num[i]!=i,我们把num[i]应该在它该有的位置,既num[num[i]]=num[i],

此时如果num[i] == num[num[i]],说明number[i]已经出现过,那就找到了重复的数字;

此时如果num[i] != num[num[i]],那就把num[i]放到number[num[i]]上去,处理num[num[i]],直到重复或者与i相等。
 

// JAVA

public class Solution {
    public boolean duplicate(int numbers[],int length,int [] duplication) {
        
		if(numbers==null || numbers.length==0) {
			duplication[0]=-1;
			return false;
		}
        
		for(int i=0;i<numbers.length;i++) {    //遍历数组
			while(numbers[i]!=i) {             // 直到找到num[i]=i,才继续比较下一个
				if(numbers[i]==numbers[numbers[i]]) {    //若存在重复元素
					duplication[0]=numbers[i];
					return true;
				}
				swap(numbers,i,numbers[i]);
			}
		}
        return false;

	}

	private static void swap(int[] num,int i,int j) {
		int tmp=num[i];
		num[i]=num[j];
		num[j]=tmp;
	}
}

 

其他思路:利用Hash或Set集合,时间复杂度O(n), 空间复杂度O(n); 

 

习题拓展:不修改数组找到重复数字,要求空间O(1)

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

显然Hash和Set方法是不能用了。

解题思路:二分法;对于一个整数范围i~j,如果在这个范围内的整数的数量超过j-i+1,那么此范围内的整数中必然有整数会出现多次。因此选定范围1~n/2,并记录输入数组中在此范围内的元素的数量,若数量大于n/2,则在此整数范围内必然有整数在数组中出现了多次,否则在范围(n/2)+1~n内必然有整数在数组中出现多次。对确定出现重复整数的范围再进行前面的划分和计数操作,直到找到重复的数字。

 

 

偷懒的思路:先排序,再二分查找
 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值