美文网首页
《剑指offer》3.数组中重复的数字

《剑指offer》3.数组中重复的数字

作者: Houtasu | 来源:发表于2019-07-16 13:49 被阅读0次

    唔,实习公司提转正时主动辞职了。然后一毕业就失业了,投了几十分简历,连个面试机会都不给。
    于是决定闭门修炼,先把基础提上去吧。遂准备把剑指offer上面的题全部实现一遍。
    剑指offer上的代码是用c++实现的,我主要是用的python,正好可以整一套python的版本。虽然网上也早有前辈用python实现过了。。。
    但算法必须要自己理解了才是自己的,所以自己还是要全部实现一遍。
    废话说完了,下面正式开始了。

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

    使用python最简单的方法使用collections里的Counter方法。它会自动统计每一个元素出现的次数。最后输出所有个数大于1 的即可。内部实现是用的字典(哈希表),也可以直接用字典来做,相当于手动实现一遍Counter函数。

    def duplicate_number(nums):
        c = collections.Counter(nums)
        return [x for x in c if c[x] > 1]
    

    时间复杂度为O(n),空间复杂度也为O(n),因为需要维护一个n大小的哈希表。
    书中提到了另一种算法。因为数组中所有数字的大小均在0~n-1的范围内。这个范围和数组的下标范围是一致的,意味着可以用数字直接做下标且不会越界。所以可以直接把数字调整到和数字相等下标的位置上。
    比如题中给出的数组{2,3,1,0,2,5,3},第一个数字是2,比较下标2上的数字1,发现不相等,那么把它和下标2上的数字对换,变成{1,3,2,0,2,5,3}。现在第一个数字是1,和下标1上的数字3还是不相等,那么再和下标1上的数字对换,变成{3,1,2,0,2,5,3}。这样一直换下去,确保每个数字都和它的下标是相等的。那么如果遇到重复的数字,比如下标4上的2,当它想换到下标2上时,发现下标2上已经有一个数字2了,那么就表示这个数字重复了。这样在本地数组上就完成了操作,不需要额外分配空间,所以空间复杂度就是O(1)。
    python实现的代码如下:

    def duplicate_number_method_2(nums):
        res = set()
        i = 0
        while i < len(nums):
            if nums[i] != i:  # 判断需不需要换位置
                c = nums[i]
                if nums[i] != nums[c]:  # 判断是不是重复的数字,不是则交换,是则添加到结果集中
                    nums[c], nums[i] = nums[i], nums[c]
                else:
                    res.add(c)
                    i += 1
            else:  # 不需要换位置则直接跳到下一个
                i += 1
        return res
    

    一个循环,虽然有时候i的值不会增加,但对于每个位置来说,要不交换,要么不交换,所以时间复杂度还是O(n)级别的。

    相关文章

      网友评论

          本文标题:《剑指offer》3.数组中重复的数字

          本文链接:https://www.haomeiwen.com/subject/lsuzkctx.html