欢迎访问 生活随笔!

生活随笔

当前位置: 首页 > 编程资源 > 编程问答 >内容正文

编程问答

剑指offer03.数组中重复的数字

发布时间:2025/3/21 编程问答 17 豆豆
生活随笔 收集整理的这篇文章主要介绍了 剑指offer03.数组中重复的数字 小编觉得挺不错的,现在分享给大家,帮大家做个参考.

剑指offer03.数组中重复的数字

      • 题目
      • 第一种解法
      • 第二种解法
      • 第三种解法
      • 值得一提的东西

题目

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

示例 1:

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

第一种解法

一个简单的暴力方法就是先把输入的数组排序.从排序的数组中找出重复的数字是一件容易的事情,只需要判断一个数字的下一个数字是否与本身相等即可
.但是排序一个长度为n的数组需要O(nlogn)的时间
时间复杂度较高,不可取

第二种解法

使用哈希表来解决这个问题.从头到尾按顺序扫描这个数组的每个数字.
每扫描到一个数字的时候.都可以用O(1)的时间来判断哈希表中是否存在了这个数字. 如果哈希表中没有这个数字就把他加入进去,下次再判断时就能找出来
时间复杂度 : O(n)
空间复杂度 : O(n)提高了时间复杂度的前提下是牺牲了一个大小为O(n)的哈希表为代价的

// 使用哈希表来储存数组中数字出现的次数 func findRepeatNumber(nums []int) int{// 先建造一个map, key为int类型存数组里面的值,value为bool类型存真假m := make(map[int]bool)// for range nums 取出值并且判断是否在哈希表里面存在// 若没有存在那么就是把这个值设为key,value设为true// 若下次再出现了这个值,那么就可以返回这个值了for _, num := range nums{if _,exist := m[num]; exist{return num}m[num] = true}return -1 }

第三种解法

有没有一种空间上为O(1)的更高效的解法呢?
在一个长度为 n 的数组 nums 里的所有数字都在 0 ~ n-1 的范围内 。
此说明含义:数组元素的 索引 和 值 是 一对多 的关系。
因此,可遍历数组并通过交换操作,使元素的 索引 与 值 一一对应(即 nums[i] = i )。因而,就能通过索引映射对应的值,起到与字典等价的作用。
遍历中,第一次遇到数字 x 时,将其交换至索引 x 处;而当第二次遇到数字 x 时,一定有 nums[x] = x ,此时即可得到一组重复数字。

算法流程:
遍历数组 nums ,设索引初始值为 i=0 :

若 nums[i]=i : 说明此数字已在对应索引位置,无需交换,因此跳过;
若 nums[nums[i]] = nums[i] : 代表索引 nums[i] 处和索引 ii 处的元素值都为 nums[i] ,即找到一组重复值,返回此值 nums[i] ;
否则: 交换索引为 i 和 nums[i] 的元素值,将此数字交换至对应索引位置。
若遍历完毕尚未返回,则返回 −1 。

func findRepeatNumber2(nums []int) int {// 效验参数的合法性if len(nums) <= 0 {return -1}for i := 0;i < len(nums);i++ {if nums[i] < 0 || nums[i] > len(nums) - 1{return -1}}var tmp int = 0for i := 0;i < len(nums);i++ {for nums[i] != i {if nums[i] == nums[nums[i]] {return nums[i]}tmp = nums[i]nums[i] = nums[tmp]nums[tmp] = tmp}}return -1 }

值得一提的东西

测试用例可能包含无效测试用例
如输入长度为n的数组中包含(0~n-1)之外的数字
传入空数组等等
所以我们需要先进行参数的校验合法性

总结

以上是生活随笔为你收集整理的剑指offer03.数组中重复的数字的全部内容,希望文章能够帮你解决所遇到的问题。

如果觉得生活随笔网站内容还不错,欢迎将生活随笔推荐给好友。