【剑指offer】3-数组中重复的数字

【仅用于个人学习记录分享,非商业用途】

————————————————————————————————————————

题目一描述

在一个长度为 n 的数组里的所有数字都在 0 到 n-1 的范围内。数组中某些数字是重复的,但不知道有几个数字是重复的,也不知道每个数字重复几次。请找出数组中任意一个重复的数字。

 Input:
 {2, 3, 1, 0, 2, 5}
 
 Output:
 2

题目解析

对于这种数组元素在 [0, n-1] 范围内的问题,可以将值为 i 的元素调整到第 i 个位置上进行求解。本题要求找出重复的数字,因此在调整过程中,如果第 i 位置上已经有一个值为 i 的元素,就可以知道 i 值重复。

解题代码

 class Solution:
     def duplicate(self, numbers, duplication):
         if numbers == None or len(numbers)<=1:
             return False
         for i in range(len(numbers)):
             if numbers[i]<0 or numbers[i]>len(numbers)-1:
                 return False
         for i in range(len(numbers)):
             while(numbers[i] !=i):
                 if numbers[i] == numbers[numbers[i]]:
                     duplication[0] = numbers[i]
                     return True
                 else:
                     temp = numbers[i]
                     numbers[i] = numbers[temp]
                     numbers[temp] = temp
         return False

题目二 不修改数组找出重复的数字

描述

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

题目解析

解题思路:找到规律“在1-n的范围内只有n个数字,如果超过n个数字,则一定包含重复的数字”

基于此思想,将数组长度n的1-n的数字分为m两部分,前一半为1-m,后一半为m+1~n.如果1-m的数字范围的数字,在数组中出现的个数大于m,则在这一半有重复数字,则在此范围内进行查找,相反则在另外一半查找。

题目理解

此题使用的是二分法的变体,可以理解为一种夹逼思想。先对数字范围进行分组,然后在两个分组中再进行查找。注意这里分组的不是要查找的数组,而是数组长度的范围。通过不断的缩小数字范围得到结果,而数组只是用来统计数字出现的次数。

代码实现

 class Solution:
     def duplicate(self, numbers):
         if not numbers or len(numbers)<0:
             return -1
         start = 1
         end = len(numbers)-1
         while start<=end: #注意这是左右闭合的写法
             middle = (end - start)//2 + start
             count = self.countRange(numbers, len(numbers), start, middle)
             if end == start:
                 if count >1:
                     return start
                 else:
                     break
             if count > middle - start +1: #如果数字i-m范围出现次数大于m-i+1,则此范围数字有重复
                 end = middle
             else:
                 start = middle +1
          return -1
  def countRange(self, numbers, length, start, end):
  if not numbers:
             return 0
         count = 0
         for i in range(lenght):
             if numbers[i]>= start or numbers[i] <= end:
                 count+=1
             return count
posted @ 2020-07-15 20:27  szxyx  阅读(222)  评论(0编辑  收藏  举报