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

算法思想:
对于特殊的数组:长度为n的数组,所有数字都在0~n-1的范围内。

  • 最简单的方法是对这个数组进行排序,然后对数组进行扫描,扫描数组的时间复杂度为O(n)
  • 利用哈希表解决问题,从头到尾按照顺序扫描数组中的每一个元素,每次扫描一个元素用O(1)的时候判断哈希表中是否有这个元素。如果哈希表中没有,则把它加入哈希表;如果哈希表中已经有了,则找到重复元素
  • 利用这个数组的特性进行重复元素的查找。如果这个数组中没有重复的元素,当数组排序之后,下标 i 的位置上是数字 i。我们在这里可以认为数字m出现在下标为i的位置上是数字m应该出现的位置。但是由于数组中存在重复的数字,因此有些下标为 i 位置出现的数字不是m
    算法思想:
    假定: 下标 i 数字m表示 数组Lst表示
  • 对 下标 i 进行遍历,判断 i ?= m*
  • if i == m 则继续遍历 i +=1
  • if i != m 比较 m ?= Lst[m]
    - if m == Lst[m] 则找到重复元素
    - ##我们关心的是数字m看出现的次数。数字m第一次出现在下标 i 的位置上(下标i和数字m不等),第二次又出现在下标为m的位置上,m就是我们需要查找的重复数字。由于数组中存在重复数字,所以某些位置上的下标和位置上的数字对应的值是不同的,也就是第一次出现的下标为i的位置和位置上的元素不同,但是m == Lst[m],m出现在它应该出现的位置上。m为重复元素。
    - if m != Lst[m] 则交换Lst[i]和Lst[m] 继续遍历 i +=1
    - ##m数字只出现一次,在下标为 i 的位置上,下标和下标上的数字不对应。交换Lst[i]和Lst[m],又Lst[i] = m,这一步将数字m放到了它应该在的地方。 i += 1继续进行遍历
'''
Creat by HuangDandan
2018-08-18

解题思路:
思路1-直接对数组进行排序,排序方法可以任选,然后进行顺序遍历 时间复杂度和排序方法有关
思路2-顺序扫描数组,利用哈希表检查是否出现过:时间复杂度O(n),空间复杂度O(n)
思路3-顺序扫描数组,在数组相对应的位置i上看数字是否是i: Lst[i] == i
如果是,继续遍历下一个;
如果不是,计数值为m,比较j与m位置的数字:
    如果相等,则返回重复数字
    如果不相等,则交换i和m位置对应的数值,继续循环

'''




def mothod1(Lst):
    #冒泡排序,排序后的列表temp
    #i循环的次数
    #j两两比较的次数
    for i in range(len(Lst)-1):
        for j in range(len(Lst)-i-1):
            if Lst[j] > Lst[j+1]:
                Lst[j],Lst[j+1] = Lst[j+1], Lst[j]

    for k in range(0,len(Lst)-1):
        if Lst[k+1] == Lst[k]:
            return Lst[k]

import numpy as np
def mothod2(a):
    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]


def mothod3(Lst):   #返回一个重复的值
    for index, value in enumerate(Lst):
        while value != index:
            if Lst[value] == value:
                return value
            else:
                Lst[index], Lst[value] = Lst[value], Lst[index]




def mothod4(a): #返回一个重复的值
    for i in range(len(a)):
        while a[i] != i:    #非常关键,当这个条件满足时,一直执行,直到不满足为止
            if a[a[i]] == a[i]:
                return a[i]
            else:
                a[a[i]], a[i] = a[i], a[a[i]]   #目标是遍历交换使得a[a[i]] == a[i]成立,返回a[i],一定可以找到,所以不会是死循环

def mothod5(a): #返回多个重复的值,时间很慢
    temp = []
    for i in range(len(a)):
        while a[i] != i:    #非常关键,当这个条件满足时,一直执行,直到不满足为止
            if a[a[i]] == a[i]:
                temp.append(a[i])
            else:
                a[a[i]], a[i] = a[i], a[a[i]]   #目标是遍历交换使得a[a[i]] == a[i]成立,返回a[i],一定可以找到,所以不会是死循环
    return temp

if __name__ == "__main__":
    Lst1 = [0,1,2,3,4,6,4]
    Lst2 = [0,1,2,3,4,6,6]
    Lst3 = [0,1,2,3,4,6,4,6]
    Lst4 = [2,5,4,2,5,3]
    Lst5 = [1, 0]
    print(Lst1)
    print("----------------------------------------")
    # print(max(Lst1))
    #print(mothod4(Lst1))
    print(mothod2(Lst1))
    #mothod3(Lst3)
    # Lst2 = [None for i in range(10)]
    # print(Lst2)
'''