剑指Offer——Day 4

90 阅读4分钟

1、 数组中重复的数字

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

### 一、暴力枚举
### 不考虑时间复杂度和空间复杂度,只求解
### 时间复杂度O(n),空间复杂度O(n)
class Solution(object):
    def findRepeatNumber(self, nums):
        list1=[]
        length=len(nums)
        for i in range(length):
            if nums[i] not in list1:
                list1.append(nums[i])
            else:
                return nums[i]
###二、时间复杂度优先
###哈希表
### 时间复杂度O(n),遍历,查找;空间复杂度O(n),哈希表占用;
class Solution(object):
    def findRepeatNumber(self, nums):
        dict={}
        length=len(nums)
        for i in range(length):
            if not dict.get(nums[i]):
                dict[nums[i]]=1
            else:
                dict[nums[i]]=2
                return nums[i]
###哈希表
### 时间复杂度O(n),空间复杂度O(n)
class Solution:
    def findRepeatNumber(self, nums: [int]) -> int:
        dic = set()   #哈希表(Set)记录数组的各个数字
        for num in nums:
            if num in dic: return num   #如果该元素在哈希表内,说明重复
            dic.add(num)   #不在,添加
        return -1  #若没有重复元素返回的值
###空间复杂度优先
# 指针+原地排序数组
### 时间复杂度O(nlogn),空间复杂度O(1)
class Solution(object):
    def findRepeatNumber(self, nums):
        nums.sort()
        length=len(nums)
        for i in range(1,length):
            if nums[i]==nums[i-1]:
                return nums[i]
            else:
                print("没有重复的数组")
### 原地交换
### 空间复杂度O(1),原地修改原数组;
### 时间复杂度O(n),遍历,判断和交换;
### 这里nums[i]与i是一一对应的,如果i对应多个nums[i]那么说明重复
class Solution(object):
    def findRepeatNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        length=len(nums)
        for i in range(length):
            while i!=nums[i]: ###需要使得nums[i]=i 如果已经
                if nums[nums[i]]==nums[i]:
                    return nums[i]
                else:
                    nums[i],nums[nums[i]]=nums[nums[i]],nums[i]

2、 排序数组查找数字的次数

统计一个数字在排序数组中出现的次数。
排序的考点是二分法

  • 时间复杂度 O(log N)  :  二分法为对数级别复杂度。
  • 空间复杂度 O(1) :  几个变量使用常数大小的额外空间。
###二分法
###nums是排序后的数组
###时间复杂度O(logn),空间复杂度O(1)
class Solution:
    def search(self, nums , target )  :
        left,right=0,len(nums-1)
        i,j=0,len(nums)-1
        while i<=j:
            m=(i+j)//2
            if nums[m] > target:
                j=m-1
            elif nums[m] <target:
                i=m+1
            elif nums[m] == target:
                i=m+1
        right=i                 #i即为target的右索引,指向的是>target的第一个数
        if j>=0 and nums[j] != target:
            return -1
        i,j=0,len(nums)-1
        while i<=j:
            m=(i+j)//2
            if nums[m] > target:
                j=m-1
            elif nums[m] <target:
                i=m+1            
            elif nums[m] == target:
                j=m-1
        left = j                 #j即为target的左索引,指向的是<target的第一个数
        return right - left - 1  #对于target的这个区域的右索引是right,左索引是left
###定义zb函数去指向索引优化代码
class Solution:
    def search(self, nums , target )  :
        def zb(target):          #i即为target的右索引,指向的是>target的第一个数
            i,j=0,len(nums)-1
            while i<=j:
                m=(i+j)//2
                if nums[m] > target:
                    j=m-1
                elif nums[m] <target:
                    i=m+1
                elif nums[m] == target:
                    i=m+1
            return i          
        return zb(target) - zb(target-1)   #zb(target)返回>target的第一个数,zb(target-1)返回=target的第一个数

##暴力解法
##统计一个数字在任意数组中出现的次数
### 计数器count
###时间复杂度O(n),遍历,判断;空间复杂度O(1)
class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        count=0
        for each in nums:
            if each==target:
                count   =count + 1
        return count
###建立字典计数每个数字重复出现的次数
###时间复杂度O(n),遍历,判断;空间复杂度O(n)
class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        dict={}
        for each in nums:
            if each in dict:
                dict[each]=dict[each]+1
            else:
                dict[each]=1
        a=dict.get(target)
        return a if a else 0

3、 0-n-1中缺失的数字

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

示例 1:

输入: [0,1,3]
输出: 2

示例 2:

输入: [0,1,2,3,4,5,6,7,9]
输出: 8
###二分法
###时间复杂度O(logn),空间复杂度O(1)
class Solution(object):
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        length=len(nums)###排序数组用二分法
        i,j=0,length-1
        while i <= j:
            m= (i+j)//2 
            if nums[m] == m:
                i = m+1
            else:
                j=m-1
        return i
###暴力解法
###时间复杂度O(n),空间复杂度O(n)
class Solution(object):
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        length=len(nums)
        list1=list(range(length+1))  #范围
        for i in range(length):
            list1.remove(nums[i])
        for each in list1:           
            return each 
###哈希表
###时间复杂度O(n),3次遍历;空间复杂度O(n)
class Solution(object):
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        dict={}
        length=len(nums)
        for i in range(length+1):
            dict[i]=1  #创建一个字典
        for each in nums:
            dict[each]=0  #出现的列表的数字对应字典变为0
        for i in range(len(dict)) :
            if dict[i] == 1:  #找到那个value是1对应的key 
                return i