【算法】剑指第二版3.数组中重复数字

题干

在一个长度为n的数组里的所有数字都在0到n-1的范围内。数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。
例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。

直觉思路

  1. 排序 O(logn)

  2. 哈希表 O(n)+O(n)

分析后才能得到的思路

  1. 在没有重复数字的情况下,每个位置的数字应该和下标对应相等。

怎么想到的

这个思路怎么想到的,暂时难以清晰描述出来,只能观察题目的特点,进行思路尝试。

PS. 注意区分排序后的位置属于它的位置,假设没有重复,则每个数都有属于自己的位置。 如果有重复的数,则会出现2个数放到同一个位置的情况,也就发现了重复元素。

题目分析

[1(cur),0,1]
cur(1)的位置不对,和位置1的元素交换 -> [0,1,1]
cur(0)的位置正确,cur前进 -> [0,1(cur),1]
cur(1)的位置正确,cur前进 -> [0,1,1(cur)]
cur(1)的位置不对,交换前进行检查,发现目标位置已经有该元素,即此时的cur就是重复数字。

代码编写思路

基于[101]的分析:
从描述中,可以分享有个外循环负责遍历,内部有while循环直到cur位置的元素放在了正确位置才结束,如果不在正确位置就要交换到正确位置,交换位置之前需要检查cur位置和交换位置的值是否相等,相等则找到重复,不相等则交换。

func FindAnyDuplicates(nums []int) int {
    // 5. 输入空检查
    if len(nums) == 0 || nums == nil {
        return -1
    }
    for _, v := range nums {
        if v < 0 || v > len(nums)-1 { // 4.输入合理性检查 数字范围[0,n-1]
            return -1
        }
    }
    // 1. 遍历数组
    for i, _ := range nums {
                // 2. 内循环直到把cur位置放的就是cur值才结束
        for nums[i] != i {
            // 3. 如果交换的目标位置值就是cur值,说明出现重复
            if nums[i] == nums[nums[i]] {
                return nums[i]
            }
            // 3. 把当前元素交换到属于它的位置 // YC: 不是放到排序后的位置 // YC:假设数组没有重复,则cur就被交换到了排序后的位置 // TODO:在有重复元素的情况下,并不是交换到属于他的位置。比如[23344],把2交换位置2[33244],而位置2显然不是排序后2的位置,而是属于2的位置。
            nums[i], nums[nums[i]] = nums[nums[i]], nums[i]
        }
    }
    return -1
}

速记

每个位置的数字与其对应的下标相等

猜你喜欢

转载自www.cnblogs.com/yudidi/p/12326711.html