在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数组中任意一个重复的数字。
题解:题目中的数字范围为0~1,因此有一个最简单的思路:以数组nums中的长度创建数组,nums中的数值为下标,不会越界。
第一种:直接排序,有数值相等的时候那么就是重复的数字。
第二种:哈希表的思想,将nums数组中相应的数字放入辅助数组中以该数字为下标,并且数值加1,当某个位置的值大于1的时候,说明该数字重复。
第三种:第二种方法的改进,如题解所述,直接将一个数放入数组中相应的下标位置,当该值与下标位置的值相等的时候,说明该值重复了。
例如:数组[0,0,1,3],第一个0的位置正确,第二个0的下标为1,但是该值本身应该放置下标为0的位置,但是该位置已经有0了,就会形成 i == nums[nums[i]],说明存在重复数值的情况。
分析:第三种方法的时间复杂度为O(n)。如代码中,当i == k的时候进入了while循环,那么一定存在k之后的某个时候是不会再次进入while中。
完整代码
1 /** 2 * @author: wooch 3 * @create: 2020/02/14 4 */ 5 6 import java.util.Arrays; 7 8 /** 9 * 找出数组中重复的数字。 10 * 在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内。 11 * 数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。 12 * 请找出数组中任意一个重复的数字。 13 */ 14 public class P3_FindRepeatNumber { 15 public int findRepeatNumber(int[] nums) { 16 // Arrays.sort(nums); 17 // int res = -1; 18 // for (int i = 0; i < nums.length; i++) { 19 // if (nums[i] == res) { 20 // return res; 21 // } else { 22 // res = nums[i]; 23 // } 24 // } 25 // return res; 26 27 // int len = nums.length; 28 // int[] arr = new int[len]; 29 // for (int i = 0; i < len; i++) { 30 // arr[nums[i]]++; 31 // if (arr[nums[i]] > 1) { 32 // return nums[i]; 33 // } 34 // } 35 // return 0; 36 37 38 for (int i = 0; i < nums.length; i++) { 39 while (i != nums[i]) { 40 if (nums[i] == nums[nums[i]]) { 41 return nums[i]; 42 } else { 43 swap(nums, i, nums[i]); 44 } 45 46 } 47 } 48 return -1; 49 } 50 51 private void swap(int[] nums, int i, int j) { 52 int temp = nums[i]; 53 nums[i] = nums[j]; 54 nums[j] = temp; 55 } 56 }
原文:https://www.cnblogs.com/baishouzu/p/12308106.html