2 数组中重复的数字--剑指offer--python实现

1. 题目描述

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

2. 题目解析

2.1 考察问题

  此问题考察数组查找问题。
  查找重复元素,所以一定涉及到计数操作
  问题中提到所有数字在0到n-1之间,这个规律告诉可以直接用一个长度为n的1维数组计数,下标为目标数组中的对应元素,存储值为元素出现次数。
  如果没有这个规律,那么只能考虑使用hashMap来计数了。

2.2 解决办法

  1. 遍历+1维数组计数
      此方法想法简单,遍历目标数组,将对应计数加1,判断重复可以提前退出,我想你应该已经想到怎么做了。
    时间复杂度 O ( n ) O(n) O(n),空间复杂度 O ( n ) O(n) O(n)
      到这里,你是不是应该考虑优化一下,空间复杂度有点高,继续看。
  2. 遍历+目标数组原地计数
      元素范围0到n-1,不仅仅允许直接使用数组而不是hashMap计数,而且考虑到元素有上限,可以以目标数组下标作为目标数组对应元素计数,此时计数不再加1,而是加n或者大于n的数即可。这样当考察到对应下标时,如果元素值已经大于n了,说明该下标出现过。
      这里有一个问题,改变了目标数组元素值,那怎么保证每次能够拿到真正的元素呢,这时候就可以通过元素对n取余的操作来还原元素本来的值。
      时间复杂度为 O ( n ) O(n) O(n),空间复杂度为 O ( 1 ) O(1) O(1)

3. 代码实现

3.1 1维数组计数

class Solution:
    # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
    # 函数返回True/False
    def duplicate(self, numbers, duplication):
        # write code here
       list_count = [0 for x in range(0, len(numbers))] ## 列表推导式,很实用
       for num in numbers:
           if list_count[num] == 1:
               duplication[0] = num
               return True
           list_count[num] += 1
       return False

3.2 目标数组原地计数

class Solution:
    # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
    # 函数返回True/False
    def duplicate(self, numbers, duplication):
        # write code here
        len_num = len(numbers)
        for i in range(0, len_num):
            index = numbers[i] % len_num ## 这步特别关键
            numbers[index] += len_num
            if numbers[index] >= 2*len_num:
                duplication[0] = index
                print(index)
                return True
        return False

4. 心得

  我当时没有想到用元素取余方法还原本来的值,所以导致自己写出了很复杂的代码,虽然也正确,但是显然违反了代码的可读性和易实现性。
  元素取余,元素位操作,元素的位的运算(异或,与,或)等都是些有用的技巧,可以帮助优化代码。
  下面是没有用取余实现的代码,复杂度连我自己都有点看不懂了。

class Solution:
    # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
    # 函数返回True/False
    def duplicate(self, numbers, duplication):
        # write code here
        len_num = len(numbers)
        for i in range(0, len_num):
            if numbers[i] >= 2 * len_num:
                duplication[0] = i
                print("1 out = " + str(i))
                return True
            elif numbers[i] >= len_num:
                if numbers[numbers[i] - len_num] >= len_num:
                    duplication[0] = numbers[i] - len_num
                    print("2 out = " + str(duplication[0]))
                    return True
                numbers[numbers[i] - len_num] += len_num
            else:
                if numbers[numbers[i]] >= len_num:
                    duplication[0] = numbers[i]
                    print("3 out = " + str(duplication[0]))
                    return True
                numbers[numbers[i]] += len_num
        return False
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值