数组中重复的数字
在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
Input: {2, 3, 1, 0, 2, 5, 3} Output: 2或3一看这个题要求重复的数字,首先想到的就是用计数法,找到一个个数大于1的就可以返回结果了。
class Solution { public int findRepeatNumber(int[] nums) { if(nums == null || nums.length == 0) return -1; int[] count = new int[nums.length]; for(int i = 0; i < nums.length; i ++){ count[nums[i]] ++; if(count[nums[i]] > 1) return nums[i]; } return -1; } }这样做时间复杂度和空间复杂度都是O(N),一旦要求空间复杂度是O(1)这样就行不通了、、、
抽屉原理指的是n个元素,n-1个抽屉,编号为i的抽屉放一个对应的元素i,一定有其中一个抽屉x需要放两个元素x,所以我们要找的这个重复元素就是x。
所以这种数组元素在 [0, n-1] 范围内的问题,可以将值为 i 的元素调整到第 i 个位置上进行求解。本题要求找出重复的数字,因此在调整过程中,如果第 i 位置上已经有一个值为 i 的元素,就可以知道 i 值重复。
以 (2, 3, 1, 0, 2, 5, 3) 为例,遍历到位置 4 时,该位置上的数为 2,但是第 2 个位置上已经有一个 2 的值了,因此可以知道 2 重复:
class Solution { public int findRepeatNumber(int[] nums) { if(nums == null || nums.length == 0) return -1;//判断一下非法输入 for(int i = 0; i < nums.length; i ++){ while(nums[i] != i){//只要当前位置数字和当前位置不匹配,就要执行,直到找到当前位置应该放的数字 if(nums[nums[i]] == nums[i]) return nums[i];//如果当前数字应该放的位置上已经有了对的数字,就返回结果 else{ //否则就交换 int tmp = nums[i]; nums[i] = nums[tmp]; nums[tmp] = tmp; } } } return -1; } }