数组中重复的数字

找出数组中重复的数字。

 


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

示例 1:

输入: [2, 3, 1, 0, 2, 5, 3] 输出:2 或 3

限制:

2 <= n <= 100000


方法一:哈希表(最自然,但是要额外空间)
最容易想到用哈希表判重,这种方法是最自然的。

分析:这种方法不修改原始数组,但是使用了 O(N) 空间,使用空间换时间,是最正常的思路,时间复杂度是O(N)。

方法二:排序(也比较容易想到,但是要排序,复杂度高)
排序以后,再遍历一遍就知道哪个重复了。

分析:这个方法其实比较容易想到,但是时间复杂度是 O(N log N),同时也修改了原始数组。

方法三:把数组视为哈希表(因为条件的缘故可以直接根据索引确定,这个方法重点理解)

 

 

程序实例:

1 import java.util.*; 2 3 public class Problem03 { 4 public static void main(String[] args) { 5 6 //方法4重点理解 7 int []nums=new int[]{2, 3, 1, 0, 2, 5, 3}; 8 9 System.out.println(solution3(nums)); 10 } 11 public static int solution(int []nums){ 12 ////使用map,时间复杂度O(n),空间复杂度O(n),不改变原数组 13 Map<Integer,Integer> map=new HashMap<>(); 14 for (int num : nums) { 15 if(!map.containsKey(num)) 16 map.put(num,1); 17 else 18 return num; 19 } 20 return -1; 21 } 22 public static int solution2(int []nums){ 23 ////使用set,时间复杂度O(n),空间复杂度O(n),不改变原数组 24 Set<Integer> set=new HashSet<>(); 25 for (int num : nums) { 26 if(!set.contains(num)) 27 set.add(num); 28 else 29 return num; 30 } 31 return -1; 32 } 33 public static int solution3(int []nums){ 34 //使用排序加循环,时间复杂度O(nlogn),空间复杂度O(1) 35 Arrays.sort(nums); 36 int first=nums[0]; 37 for (int i = 1; i < nums.length; i++) { 38 if(first==nums[i]) 39 return nums[i]; 40 first=nums[i]; 41 } 42 return -1; 43 } 44 public static int solution4(int []nums){ 45 //使用原地哈希(找到重复的数字就是发生了哈希冲突),时间复杂度O(n),空间复杂度O(1) 46 47 //如果没有重复数字,那么正常排序后, 48 // 数字i应该在下标为i的位置, 49 // 所以思路是重头扫描数组,遇到下标为i的数字如果不是i的话, 50 // (假设为m),那么我们就拿与下标m的数字交换。 51 // 在交换过程中,如果有重复的数字发生,那么终止返回ture 52 53 //{2, 3, 1, 0, 2, 5, 3},举例一步一步的走一遍 54 int temp; 55 for(int i=0;i<nums.length;i++){ 56 while (nums[i]!=i){ 57 if(nums[i]==nums[nums[i]]){ 58 //如果冲突 59 return nums[i]; 60 } 61 temp=nums[i]; 62 nums[i]=nums[temp]; 63 nums[temp]=temp; 64 } 65 } 66 return -1; 67 } 68 public static int solution5(int []nums){ 69 //使用桶排序的思想(本质是hash),时间复杂度O(n),空间复杂度O(n) 70 //题目给了数组值的范围(小于数组长度),所以不会越界! 71 int[] arr = new int[nums.length]; 72 for(int i = 0; i < nums.length; i++){ 73 arr[nums[i]]++; 74 if(arr[nums[i]] > 1) return nums[i]; 75 } 76 return -1; 77 } 78 79 80 }

 

 

 来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof




__EOF__

本文作者程序员小宇
本文链接https://www.cnblogs.com/treasury/p/12594214.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   程序员小宇  阅读(239)  评论(0编辑  收藏  举报
编辑推荐:
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
点击右上角即可分享
微信分享提示