剑指Offer-找出数组中的重复数字

106 阅读2分钟

题目

给定一个长度为 nn 的整数数组 nums,数组中所有的数字都在 0∼n−10∼n−1 的范围内。 数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。 请找出数组中任意一个重复的数字。 注意:如果某些数字不在 0∼n−10∼n−1 的范围内,或数组中不包含重复数字,则返回 -1; 数据范围 0≤n≤10000≤n≤1000 样例 给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。

返回 2 或 3。

解析

方法一

本题可以利用在每个数字都在0 ~ n - 1这一点来做,基本思想就是,将每个数字放到对应的位置(即使得nums[i] = i。
当 i != nums[i] && nums[nums[i]] != nums[i]时,说明nums[i]不在最终位置上,就要交换两数。若交换完还是 i != nums[i],则重复该操作。每次循环就会有一个数放到对应位置上
当 i != nums[i] && nums[nums[i]] == nums[i],就说明nums[i]出现了多次,结果就直接返回nums[i]
若循环结束未找到任何重复的数,就返回-1

方法二

直接使用map或set对每个数计数即可,若发现某数已在set或者map[x] != 0,就找到了重复数,直接返回x即可。若最后没有重复数,返回-1

代码

C++

class Solution {
public:
    int duplicateInArray(vector<int>& nums) {
        int n = nums.size();
        for (auto x: nums)
            if (x < 0 || x >= n) return -1;
        for (int i = 0; i < n; i ++ ) {
            while (i != nums[i] && nums[i] != nums[nums[i]]) 
                swap(nums[i], nums[nums[i]]);
            if (i != nums[i] && nums[i] == nums[nums[i]])
                return nums[i];
        }
        return -1;
    }
};

Python

class Solution(object):
    def duplicateInArray(self, nums):
        """
        :type nums: List[int]
        :rtype int
        """
        n = len(nums)
        
        for x in nums:
            if x < 0 or x >= n:
                return -1
    
        for i in range(n):
            while i != nums[i] and nums[nums[i]] != nums[i]:
                nums[nums[i]], nums[i] = nums[i], nums[nums[i]]
            if i != nums[i] and nums[nums[i]] == nums[i]:
                return nums[i]
        return -1
class Solution(object):
    def duplicateInArray(self, nums):
        """
        :type nums: List[int]
        :rtype int
        """
        n = len(nums)
        s = set()
        ans = -1
        
        for x in nums:
            if x < 0 or x >= n:
                return -1
            if x in s:
                ans = x
            s.add(x)
            
        return ans
        

Go

func duplicateInArray(nums []int) int {
    n := len(nums)
    for _, v := range nums {
        if v < 0 || v > n - 1 {
            return -1
        }
    }
    
    for i := 0; i < n; i ++ {
        for i != nums[i] && nums[i] != nums[nums[i]] {
            nums[i], nums[nums[i]] = nums[nums[i]], nums[i]
        }
        
        if i != nums[i] && nums[i] == nums[nums[i]] {
            return nums[i]
        }
    }
    
    return -1
}
func duplicateInArray(nums []int) int {
    cnt := make(map[int]int)
    n := len(nums)
    ans := -1
    
    for _, v := range nums {
        if v < 0 || v >= n {
            return -1
        }
        cnt[v] ++ 
        if cnt[v] > 1{
            ans = v
        }
    }
    
    return ans
}