【A-剑指offer】 python实现 3-找出数组中的重复数字 不修改原先数组

版权声明:转载请声名出处,谢谢 https://blog.csdn.net/u010591976/article/details/82016618

题目描述:
在一个长度为n的数组里的所有数字都在1-n范围内,数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。请找出数字中任意一个重复的数字。前提条件是不能修改数组

哈希表法:
建立一个全部为0值,长度为 n 的哈希表,如果没有重复数字,哈希表中所有的值全部为1,不存在第二次赋值为1的情况
1-从头到尾扫描原数组Lst,下标为i的位置上对应的数字是m
2-判断哈希表中下标为m的位置上值是否为0
3-为0,将数组数字m放到哈希表中,即令哈希表总对应的值为1(1是这里的一个标记值,用来判断)
表示哈希表中下标为m的位置上没有对应值,即原列表中第一次出现数字m
4-为1,返回数字m,数字m为重复的数字。
因为哈希表中已经存在数字m,在此基础上原列表i位置上又出现了数字m,数字m为重复的数字

如果避免使用O(n)的空间消耗,可以使用二分法查找算法,但是增加了一个统计数字出现的个数过程.

二分查找算法+统计区间数字
- 将1-n数字分为两部分: startN—midN 和 midN—endN两部分 即 1—m 和 m+1—n两部分
如果1—m区间内的数字超过了m,那么这一半的区间内一定存在重复的数字;否则另外一半一定存在重复的数字。我们可以继续将包含重复数字的区间一分为二,直到找到重复的数字。

  • 找到重复的数字:当数字范围startN == endN的时候,判断该数字出现的次数超过1,则找到重复数字返回该数字startN.
  • 最后剩下两个数字 3,4 由于整除的计算,最后找到重复数字时,对应的情况是startN == endN
'''
Creat by HuangDandan
2018-08-24
[email protected]

'''

#哈希表 需要额外的空间,空间消耗为O(n)
import numpy as np
def HashFind(a):                        #哈希表 需要额外的空间,空间消耗为O(n)
    num_array = np.zeros(len(a))
    for i in range(len(a)):
        if num_array[a[i]] == 0:
            num_array[a[i]] += 1
        else:
            return a[i]

#二分法查找统计思想
#数值范围1-n,一共n-1个数字
#循环实现,循环改变索引值进行二分:
def getDuplication(a):
    m = len(a)
    startN = 1      #列表数值范围最小值
    endN = m      #列表数值范围最大值

    while startN <= endN:
        midN = (startN+endN)>>1     #二分法中间值
        numbers = 0
        for i in range(m):
            if (a[i]<= midN) & (a[i]>= startN):
                numbers += 1
        if numbers > (midN - startN+1):     #关键(midN - startN+1),如果没有重复元素,startN与midN范围间相差的数字个数
            startN, endN = startN, midN
        else:
            startN, endN = midN+1, endN
        if startN == endN:                  #最后判断数组出现的次数
            number = 0
            for j in a:
                if j ==startN:
                    number += 1
            if number > 1:
                return startN
            else:
                break
    return False

if __name__ == "__main__":    
    Lst2 = [2,2,3,4,6,6]
    Lst3 = [1,2,3,4,6,4,6]
    Lst4 = [2,5,4,2,5,3]
    Lst5 = [1, 0]
    print(Lst2)
    print("----------------------------------------")
    #print(HashFind(Lst2))
    print(getDuplication(Lst2))

温故:
对于二分法思想+统计数字的方法:
当1—m区间范围,数组中该范围的数字出现的次数等于m时,应该怎么处理。理论上说可能存在重复数字也可能不存在。

猜你喜欢

转载自blog.csdn.net/u010591976/article/details/82016618