JZ50 数组中重复的数字 python

JZ50 数组中重复的数字

在这里插入图片描述
my version
出错记录:

  1. 没有考虑输入为空的情况[]

时间复杂度O(n) 空间复杂度O(n)

class Solution:
    def duplicate(self , numbers ):
        if numbers:
            n = [0] * len(numbers)
            for i in numbers:
                if i < 0 or i >= len(numbers):
                    return -1
                elif n[i] != 0:
                    return i
                else:
                    n[i]+=1
        else:
            return -1

book method1
考虑空间复杂度为O(1)的情况 时间复杂度仍为O(n)
数组中数字范围0~n-1,若无重复数字则排序后数字i出现位置的下标也为i

class Solution:
    def duplicate(self , numbers ):
        if numbers:
            for i in range(len(numbers)):
                if numbers[i] >0 and numbers[i] <len(numbers):
                    while numbers[i] != i:
                        if numbers[numbers[i]] != numbers[i]:
                            tmp = numbers[numbers[i]]
                            numbers[numbers[i]] = numbers[i]
                            numbers[i] = tmp
                        else:
                            return numbers[i]
        return -1

book method2
当题目改为长度为n+1,数字范围在1~n范围内时才适用如下算法,
否则若题目为长度为n,数字范围在0~n-1出现例如[2,1,3,1,4] 则n=5,划分为0~2和3~4其中<=2且>=0的有3个和位数3相同,无法找到,
因此,只有在题目为长度为n+1,数字范围在1~n范围内时,n=4,化分为1~2和3~4,其中<=2且>=1的有3个>位数2因此重复的数出现在此区域内,再继续二分查找。
数字范围为1~n共n个,可长度为n+1说明一定有重复的。

不修改数组本身 考虑类似二分查找的方法,统计相应范围内数字出现的次数 时间复杂度O(nlogn) 空间复杂度O(1)
出错记录:

  1. 二分查找时 mid = (end - start) / 2 + start, 否则查找后半段的下标会出错
class Solution:
    def countRange(self, start, end, numbers):
        count = 0
        for i in range(len(numbers)):
            if numbers[i] <0 or numbers[i] >=len(numbers):
                return -1
            elif numbers[i] >= start and numbers[i] <= end:
                count += 1
        return count
    
    def duplicate(self , numbers ):
        if numbers:
            start = 1
            end = len(numbers)-1
            while (start <= end):
                mid = (end - start) // 2 + start

                count = self.countRange(start, mid, numbers)
                if start == end:
                    if count >1 :
                        return start
                    else:
                        break
                if count > (mid-start)+1:
                    end = mid
                else:
                    start = mid + 1
        return -1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值