剑指offer 重数组中重复的数字

https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/

剑指offer 重数组中重复的数字_第1张图片
首先一个很重要的信息是在一个长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内,第二个就是数组中重复数字的次数不确定,但肯定至少重复两次

这道题好像加了很多测试样例,

sort

直接sort一遍,然后for循环逐个判断即可

class Solution:
    def findRepeatNumber(self, nums: List[int]) -> int:
        nums.sort()
        ans=0
        for i in range(len(nums)-1):
            if nums[i]==nums[i+1]:
                ans = nums[i]
        return ans

剑指offer 重数组中重复的数字_第2张图片

hash

开一个等长的数组,然后一个for判断

class Solution:
    def findRepeatNumber(self, nums: List[int]) -> int:
        appeared=set()
        for num in nums:
            if num in appeared:
                return num
            appeared.add(num)        

剑指offer 重数组中重复的数字_第3张图片

修改原数组作为标记

由于num的范围在0~n-1,我们可以改变nums的值,来标记这个元素是否之前出现过
例如[2, 3, 1, 0, 2, 5, 3]
我们先把它逐个+1

0 1 2 3 4 5 6
3 5 2 1 3 6 4
i
3 5 2 -1 3 6 4
i
3 5 2 -1 3 -6 4
i
3 5 -2 -1 3 -6 4
i
-3 5 -2 -1 3 -6 4
i 此时找到一个为负的数-1 返回当前的值-1
-3 5 -2 1 3 6 4

由于遍历过程中数字可能会小于0,所以我们需要取到abs
并且0是没有负数的,所以我们要先+1再遍历,否则通不过0 1 0 这种测试样例

        nums=list(map(lambda x:x+1,nums))
        for i in range(len(nums)):
            if(nums[abs(nums[i])-1]<0):
                return abs(nums[i])-1
            nums[abs(nums[i])-1]=-nums[abs(nums[i])-1]

另外之前要加1,因为 [0,1,0]这种状况0不能修改成负数,所以要把数组的每个num加1,在遍历的时候取下标再返回

利用输入数据的性质

输入数据有一个特点:所有数字都在 0~n-1 的范围内
按照这个数据的特点,我们可以得知下面两个性质
假如一个数组没有重复我们知道排序后每个数字都在它唯一的位置,如0 1 2 3 4 5
假如有一个2重复了,那么他就会挤占其它的位置 0 1 2 2 4 5
那么我们想办法判断每个元素是否在它的原来位置就行了
假设当前的值是n,下标是i,那么它最终的位置一定在n上(看上面的例子)
我们对数组进行遍历,一共有这几种情况

  1. 当前的数字不在最终位置上,判断最终位置的数字
    1. 是否和当前数字相同,如果相同则发生了冲突,说明当前数字是重复数字
    2. 如果不相同,那么可以放心的交换,此时下标i不会走,以防漏掉数字
  2. 当前位置在最终位置上,下标i直接+1
	0	1	2	3	4	5	6
	2	3	1	0	2	5	3
	
12	3	1	0	2	5	3
	i
2:	1	3	2	0	2	5	3
	i
3:	3	1	2	0	2	5	3
	i
4:	0	1	2	3	2	5	3
	i	i	i	i	i
此时发现2冲突了,返回重复数字2
class Solution:
    def findRepeatNumber(self, nums: List[int]) -> int:
        i=0
        while i<len(nums):
            if nums[i]!=i:	#不在最终位置
                if nums[i]!=nums[nums[i]]:	#不相等
                    nums[nums[i]],nums[i]=nums[i],nums[nums[i]]
                else:	#冲突
                    return nums[i]
            else:
                i+=1

剑指offer 重数组中重复的数字_第4张图片

扩展

leetcode上面这一类题目很像,都是一样的思想,把数组本身当作hash表

https://leetcode-cn.com/problems/find-the-duplicate-number/

https://leetcode-cn.com/problems/first-missing-positive/

https://leetcode-cn.com/problems/find-all-duplicates-in-an-array/

https://leetcode-cn.com/problems/find-all-numbers-disappeared-in-an-array/

你可能感兴趣的:(leetcode)