数组中重复的数字

题目描述:

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

答案:

# 方法一:借助辅助空间,输出全部重复的数字
import numpy as np
array = np.array([2,3,1,0,2,5,3,3])
def repeat(array):
    b = []
    length = len(array)
    for i in range(length):
        if array[i] in b:
            # 返回已经存在的值
            yield array[i]
        b.append(array[i])
c = set(repeat(array))
print(c) #{2,3}
# 输出重复数字重复的次数
# c1 = list(repeat(array))
# for i in c:
#     print(c1.count(i))

# 方法二:对原数组排序,遍历排序后的数组
import numpy as np
array = np.array([2,3,1,0,2,5,3])
def repeat(array):
    length = len(array)
    for i in range(length):
        for j in range(i+1,length):
            if array[j]<array[i]:
                tmp = array[i]
                array[i] = array[j]
                array[j] = tmp
    # print(array)排序后的数组
    for i in range(length):
        if i != array[i]:
            return array[i]
c = repeat(array)
print(c) #{2}


# 方法三:牛客网可通过代码
'''
从头到尾依次扫描这个数组中的每个数字。当扫描到下标为i的数字时,首先比较
这个数字(用m表示)是不是等于i。如果是,则接着扫描下一个数字;如果不是,
则再拿它和第m个数字进行比较。如果它和第m个数字相等,就找到了一个重复的数
字(该数字在下标i和m的位置都出现了);如果它和第m个数字不相等,就把第i个
数字和第m个数字交换,把m放到属于它的位置。接下来重复这个比较、交换的过程,
直到我们发现一个重复的数字。
'''
# -*- coding:utf-8 -*-
class Solution:
    def duplicate(self, numbers, duplication):
        length = len(numbers)
        if length == None:
            return False
        for index in range(length):
            if numbers[index]<0 or numbers[index]>length-1:
                return False
        for index in range(length):
            while index != numbers[index]:
                if numbers[index] == numbers[numbers[index]]:#不同位置有相同值
                    duplication[0] = numbers[index]
                    return True
                tmp = numbers[index]
                numbers[index] = numbers[tmp]
                numbers[tmp] = tmp
        return False


#方法四
import collections
def repeat(numbers):
    c = collections.Counter(numbers)
    for k,v in c.items():
        if v>1:
            return k

numbers = [1,1,1,2,2,3,4]
print(repeat(numbers))


题目变形:

在一个长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的。请找出数组中任意一个重复的数字,但是不能修改输入的数组。例如,如果输入长度为8的数组{2,3,5,4,3,2,6,7},那么对应的输出是重复的数字2或者3。

'''
我们把从1~n的数字从中间的数字m分为两部分,前面一半为1~m,
后面一半为m+1~n。如果1~m的数字的数目等于m,则不能直接判断
这一半区间是否包含重复的数字,反之,如果大于m,那么这一半
的区间一定包含重复的数字;如果小于m,另一半m+1~n的区间里
一定包含重复的数字。接下来,我们可以继续把包含重复的数字
的区间一分为二,直到找到一个重复的数字。这个过程和二分查找
算法很相似,只是多了一步统计区间里数字的数目。
二分查找对象序列为1~n的有序序列,如题目中例子对应的二分查找
序列为{1,2,3,4,5,6,7}
'''
# 统计一定范围内有序序列元素在输入数组中出现的次数
def countRange(numbers,start,end):
    if numbers == []:
        return 0
    count = 0
    length = len(numbers)
    for i in range(length):
        if numbers[i]>=start and numbers[i]<=end:
            count+=1
    return count
def repeat(numbers):
    if numbers == []:
        return -1
    length = len(numbers)
    start = 1
    end = length-1
    while start <= end:
        middle = (end+start)//2
        count = countRange(numbers,start,middle)
        if end == start:
            if count>1:
                return start
            else:
                break
        if count>(middle-start+1):
            end = middle
        else:
            start = middle+1
    return -1
a = [2,3,5,4,3,2,6,7]
print(repeat(a))#3

上面的代码针对0~n-1的数组不适用,对其改进

def countRange(numbers,start,end):
    if numbers == []:
        return 0
    count = 0
    length = len(numbers)
    for i in range(length):
        if numbers[i]>=start and numbers[i]<=end:
            count+=1
    return count
def repeat(numbers):
    if numbers == []:
        return -1
    length = len(numbers)
    start = 0
    flag = 0
    end = length-1
    while start <= end:
        if flag == 0:
            middle = start+((end-start)>>1)
        count = countRange(numbers,start,middle)
        if end == start:
            if count>1:
                return start
            else:
                break
        if count>(middle-start+1):
            end = middle
            flag = 0
        elif count == (middle - start + 1):
            middle = middle - 1
            if middle < start: #说明(start, middle)这个区间没有重复的数
                start = (start+end) // 2 + 1
                flag = 0
            else:
                flag = 1
        else:
            start = middle+1
            flag = 0
    return -1
a = [1,7,2,5,6,1,3,3]
b = [2,3,5,4,3,2,6,7]
print(repeat(b))




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值