不修改数组找出重复的数字

# 描述

在一个长度为 n+1 的数组中所有的数字都在 1~n 范围内,所以数组中至少有一个数字是重复的。
请至少找出数组中任意一个重复的数字,但不能修改输入的数组。

# 思路

采用二分法查找,时间复杂度为 O(nlogn)

在数字 1~n 中取中间值 m = (1+n) / 2, 此时数字包括 1~m, m+1~n 两段;
遍历数组,获得数字 1~m 的个数;
如果数字 1~m 的个数大于 m,说明 1~m 这一段内肯定有重复数字,那么在这一段内继续取中间值比较;
如果数字 1~m 的个数等于 m,这一段不一定有重复数字,比较后一段;
如果数字 1~m 的个数小于 m,说明 m+1~n 这一段一定有重复数字,在后一段取中间值比较;
按照上述方法一直取中间值比较,直到只剩一个数字且这个数字出现次数超过 1 ,该数字即为重复数字

# 解决

def find_dux_num(seq):
    if len(seq) <= 1 or seq is None:
        return None

    start, end = 1, len(seq) - 1  # 获取数字1,n

    while start <= end:
        mid = (start+end) // 2  # 获取中间数字
        count = count_num(seq, start, mid)  # 计算[start, mid]数字之间的数目

        # 当只取到一个数字时,如果该数字出现数目大于1,就是重复数字
        if start == end:
            if count > 1:
                return start
            else:
                break

        # 如果count数目 > 中间数字到起始数字之差,一定存在重复数字,继续在这一段中求中间数比较
        if count > mid - start + 1:
            end = mid
        # 否则在后一段中求中间数比较
        else:
            start = mid + 1

    return None


def count_num(seq, start, end):
    count = 0
    for i in seq:
        if start <= i <= end:
            count += 1
    return count


if __name__ == '__main__':
    print(find_dux_num([1, 2, 3, 4, 3]))

你可能感兴趣的:(不修改数组找出重复的数字)