leetcode刷题 剑指 Offer 03. 数组中重复的数字,Easy (Java/Python)字典+排序+原地交换

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

1.题目描述

找出数组中重复的数字。

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

示例 1:

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

限制:

2 <= n <= 100000

来源:力扣(LeetCode)

链接:剑指 Offer 03. 数组中重复的数字

著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

2.解法

评论里有人说:

自来火:这道题在原书上绝对不是简单级别啊!

它考察的是程序员的沟通能力,先问面试官要时间/空间需求!!!

只是时间优先就用字典,

还有空间要求,就用指针+原地排序数组,

如果面试官要求空间O(1)并且不能修改原数组,还得写成二分法!!!

建议直接看原书,大家自己买一本或者找一找,我就有一本,原书很有趣,面试必备。 这题有Java和Python两种代码.

2.1 哈希表(字典)

2.1.1 思路

如果还记得Hashset的概念的话,看到找出重复数字的要求应该会想到Hashset。不记得的话,可以看Java中哈希集(HashSet)概念,实现以及操作这个复习。

这道题就直接新建一个哈希表,一个个将元素放入,如果有重复add()的返回值会为false,此时就可以直接返回该重复的值。

Python中的dict采用了哈希表,最低能在 O(1)时间内完成搜索。同样的java的HashMap也是采用了哈希表实现,不同是dict在发生哈希冲突的时候采用了开放寻址法,而HashMap采用了链接法。

2.1.2 Java代码

class Solution {
    public int findRepeatNumber(int[] nums) {
        HashSet<Integer> numHash = new HashSet<Integer>();
        for(int i=0;i<nums.length;i++){
            if(!numHash.add(nums[i])){
                return nums[i];
            }
        }
        return -1;
    }
}
复制代码

2.1.3 Python代码

class Solution(object):
    def findRepeatNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        dic = {}
        for i in nums:
            if i not in dic:
                dic[i] = 0
            else:
                return i
复制代码

2.2 排序

2.2.1 思路

排序法的思路也很简单。 排序过后相同的两个值会处在相邻的位置只需要判断 ii+1 是否相同就可以了。

2.2.2 Java代码

class Solution {
    public int findRepeatNumber(int[] nums) {
        Arrays.sort(nums);
        for(int i=0;i<nums.length-1;i++){
            if(nums[i]==nums[i+1]){
                return nums[i];
            }
        }
        return -1;
    }
}
复制代码

2.2.3 Python代码

class Solution(object):
    def findRepeatNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums.sort()
        for i in range(len(nums)):
            if nums[i] == nums[i+1]:
                return nums[i]
        return None
复制代码

2.3 原地排序

2.3.1 思路

这道题使用了题目中长度为 n 的数组 nums 里的所有数字都在 0~n-1 的范围内 这个条件。 因为数组满足了这个条件,所以可以将nums[i] =i对应。

  • 首先判断值和下标是否对应,若对应继续判断下一个值
  • 之后判断值和要去的位置是否相同,若相同说明要去的位置已经有相同的数占了位置
  • 最后不符合上述两个条件,所以需要将值换到对应的下标。

2.3.2 Java代码

class Solution {
    public int findRepeatNumber(int[] nums) {
        int i = 0;
        while(i < nums.length) {
            if(nums[i] == i) {
                i++;
                continue;
            }
            if(nums[nums[i]] == nums[i]){
                return nums[i];
            } 
            int temp = nums[i];
            nums[i] = nums[temp];
            nums[temp] = temp;
        }
        return -1;
    }
}
复制代码

2.3.3 Python代码

class Solution(object):
    def findRepeatNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        i = 0
        while i < len(nums):
            if nums[i] == i:
                i += 1
                continue
            if nums[nums[i]] == nums[i]: return nums[i]
            nums[nums[i]], nums[i] = nums[i], nums[nums[i]]
        return -1
       
复制代码

Supongo que te gusta

Origin juejin.im/post/7076721961191079967
Recomendado
Clasificación