287 寻找重复数(寻找环的起点、字典)

43 篇文章 0 订阅
本文介绍了LeetCode的一道题目,要求在给定数组中找出唯一重复的数字。提出了两种解决方案,一种是利用哈希表计数,另一种是通过快慢指针寻找环的起点。代码示例分别展示了这两种方法的实现,适用于解决数组中重复元素的问题。
摘要由CSDN通过智能技术生成

1. 问题描述:

给定一个包含 n + 1 个整数的数组 nums ,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数。假设 nums 只有一个重复的整数,找出这个重复的数 。

示例 1:

输入:nums = [1,3,4,2,2]
输出:2

示例 2:

输入:nums = [3,1,3,4,2]
输出:3

示例 3:

输入:nums = [1,1]
输出:1

示例 4:

输入:nums = [1,1,2]
输出:1

提示:
2 <= n <= 3 * 10 ^ 4
nums.length == n + 1
1 <= nums[i] <= n
nums 中 只有一个整数出现两次或多次 ,其余整数均只出现一次
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/find-the-duplicate-number

2. 思路分析:

分析题目可以知道最容易想到的是使用哈希表对nums中出现的数字进行计数,因为使用是python语言所以可以使用collections.defaultdict(int)声明一个字典对nums中出现的数字进行计数,使用这个方法是最简单而且是比较高效的。除了这种方法之外,在y总的视频中讲到的是另外一个思路是寻找环的起点,感觉这种方法还是比较难想到的,其实我们可以将这些数字通过下标的方式连接起来,例如[3,1,3,4,2]可以表示为下图的形式,这样使用下标连接数字的时候那么相当于表示为链表的形式,从图中可以知道至少有两个起点指向的数字那么就是重复的数字,所以问题等价于寻找环的起点。寻找环的起点的经典方法是使用快慢指针a, b,慢指针每次走一步,快指针每次走两步这样因为存在环所以最终两个指针肯定会在一个位置相遇,假设两个指针相遇在下图中的c点,因为第一次相遇的时候快指针比慢指针肯定是多走一圈的,而且快指针比慢指针多走一倍的路程,所以根据这些关系我们得到图中c点到b点的长度为x,这样当两个指针相遇的时候我们令一个指针从最开始的位置走,另外一个指针从当前位置开始走,最终两个指针相等的位置就是环的起点。

3. 代码如下:

寻找环的起点:

from typing import List


class Solution:
    def findDuplicate(self, nums: List[int]) -> int:
        a, b = 0, 0
        while True:
            # a指针每次走一步, b指针每一次走两步, 列表中两层嵌套表示的就是每次走两步的意思
            a, b = nums[a], nums[nums[b]]
            if a == b:
                # a从开始位置走, b从当前位置开始走当两个位置系相等的时候说明是环的起点
                a = 0
                while a != b:
                    a = nums[a]
                    b = nums[b]
                return a
        return -1

字典:

from typing import List
import collections

class Solution:
    def findDuplicate(self, nums: List[int]) -> int:
        dic = collections.defaultdict(int)
        for i in range(len(nums)):
            if dic[nums[i]]:
                return nums[i]
            dic[nums[i]] += 1

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值