【日常系列】LeetCode《7·排序篇》

数据规模->时间复杂度

<=10^4 😮(n^2)
<=10^7:o(nlogn)
<=10^8:o(n)
10^8<=:o(logn),o(1)

总结

1.回顾常用排序算法
2.各排序算法的应用(归并、快排)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
小规模数据,选择使用O(n^2)的排序算法
大规模数据,选择使用O(nlogn)的排序算法

1)如何写一个通用的排序算法
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2)排序元素比较
3)分治算法思想

3.自定义排序的逻辑
4.有的时候,先对数据进行排序,可以降低复杂度

lc 912 :https://leetcode.cn/problems/sort-an-array/
提示:
1 <= nums.length <= 5 * 10^4
-5 * 10^4 <= nums[i] <= 5 * 10^4

#方案一:归并
class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        #o(n)
        self.sort_merge(nums,0,len(nums)-1,[0]*len(nums))
        return nums
    #o(nlogn):分治 
    def sort_merge(self, nums,lo,hi,tmp) -> None:
        #递归终止条件:最小子问题,无法继续分解
        if lo>=hi:return 
        #
        mid=lo+(hi-lo)//2
        self.sort_merge(nums,lo,mid,tmp)
        self.sort_merge(nums,mid+1,hi,tmp)
        self.merge(nums,lo,mid,hi,tmp)
    #归并
    def merge(self, nums,lo,mid,hi,tmp) -> None:
        #
        for i in range(lo,hi+1):
            tmp[i]=nums[i]
        #
        i=lo
        j=mid+1
        for k in range(lo,hi+1):
            if i==mid+1: #key
                nums[k]=tmp[j]
                j+=1
            elif j==hi+1: #key
                nums[k]=tmp[i]
                i+=1
            elif tmp[i]<=tmp[j]:
                nums[k]=tmp[i]
                i+=1
            else:
                nums[k]=tmp[j]
                j+=1
#方案二:二路快排:o(nlogn),o(logn)
import random
class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        self.quick_sort(nums,0,len(nums)-1)
        return nums
    #o(nlogn):分治 
    def quick_sort(self,nums,lo,hi) -> None:
        #
        if lo>=hi:return 
        #
        index=self.pivot(nums,lo,hi)
        self.quick_sort(nums,lo,index-1)
        self.quick_sort(nums,index+1,hi)
        
    #快排:o(nlogn)
    def pivot(self, nums,lo,hi) -> None:
        #随机选取pivot
        i = random.randint(lo, hi)
        nums[i],nums[hi]=nums[hi],nums[i] #换至最后,方便分区
        pivot=nums[hi]
        #分区
        less=great=lo
        while great<=hi-1:
            if nums[great]<pivot:
                nums[less],nums[great]=nums[great],nums[less]
                less+=1
            great+=1
        nums[less],nums[great]=nums[great],nums[less]
        #
        return less     
#三路快排:o(nlogn),o(logn)
import random
class Solution:
    def sortArray(self, nums: List[int]) -> List[int]:
        self.quick_sort(nums,0,len(nums)-1)
        return nums
    #o(nlogn):分治 
    def quick_sort(self,nums,lo,hi) -> None:
        #
        if lo>=hi:return 
        #
        less,great=self.pivot(nums,lo,hi)
        self.quick_sort(nums,lo,less-1)
        self.quick_sort(nums,great+1,hi)
        
    #三路快排:o(nlogn)
    def pivot(self, nums,lo,hi) -> None:
        #随机选取pivot
        j = random.randint(lo, hi)
        nums[j],nums[hi]=nums[hi],nums[j] #换至最后,方便分区
        pivot=nums[hi]
        #分区:未处理区[great,hi],其他为已处理区
        i=lo
        less=lo
        great=hi
        while i<=great:
            if nums[i]<pivot:
                nums[less],nums[i]=nums[i],nums[less]
                less+=1
                i+=1#注意:nums[i]与nums[less]已经得到处理
            elif nums[i]>pivot:
                nums[great],nums[i]=nums[i],nums[great]
                great-=1
                #注意无i+=1:此时nums[i]为待处理元素,因为之前nums[great]不明情况
            else:i+=1          
        #
        return less,great

阿里面试题 - 快速查找第二大数
在这里插入图片描述

#冒泡:时o(n),空o(1)
class Solution:
    def getsecondmax(self, nums: List[int]) -> List[int]:
    	#
    	first=-2**31
    	second=-2**31
    	#
    	for num in nums:
    		if num>first:
    			second=first
    			first=num
    		else:num>second:
    			second=num
    	#
    	return second

lc 628 :https://leetcode.cn/problems/maximum-product-of-three-numbers/
提示:
3 <= nums.length <= 10^4
-1000 <= nums[i] <= 1000

#冒泡
class Solution:
    def maximumProduct(self, nums: List[int]) -> int:
        #o(1)
        #第一小,第二小
        min1=min2=float('inf')
        #第一大,第二大,第三大
        max1=max2=max3=float('-inf')
        #o(n)
        for num in nums:
            min1,min2,_=sorted([min1,min2,num])
            _,max3,max2,max1=sorted([max1,max2,max3,num])
        #
        return max(max1*max2*max3,min1*min2*max1)

lc 88:https://leetcode.cn/problems/merge-sorted-array/
提示:
nums1.length == m + n
nums2.length == n
0 <= m, n <= 200
1 <= m + n <= 200
-10^9 <= nums1[i], nums2[j] <= 10^9

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        #o(1)
        i=m-1
        j=n-1
        k=n+m-1
        #o(n):nums1,nums2已经有序
        while j>=0:
            if i>=0 and nums1[i]>nums2[j]:
                nums1[k]=nums1[i]
                i-=1
            else:
                nums1[k]=nums2[j]
                j-=1
            k-=1
        #
        return nums1

【剑指 51】:https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof/
限制:
0 <= 数组长度 <= 50000

#逆序对:数组中的两个元素,前面的元素大于后面的元素
#方案一:暴力(超时)
class Solution:
    def reversePairs(self, nums: List[int]) -> int:
        #
        if nums==None or len(nums)<2:return 0
        #o(n^2)
        count=0
        for i in range(len(nums)):
            for j in range(i+1,len(nums)):
                if nums[i]>nums[j]:
                    count+=1
        #
        return count 
        
#方案二:归并(阶段排序):整序的过程是消逆序对(有序程度)的过程
#分治算法:类比栈(先进后出)与 DFS(深度优先遍历)
#https://www.bilibili.com/video/BV1Qk4y1r7u5?spm_id_from=333.337.search-card.all.click
class Solution:
    def reversePairs(self, nums: List[int]) -> int:
        #
        if len(nums)<2:return 0
        #o(n),o(nlogn)
        copy=[0]*len(nums) #不改变原数组
        for i in range(len(nums)):
            copy[i]=nums[i]

        count=self.sort_merge_count(copy,0,len(nums)-1,[0]*len(nums))
        return count

    def sort_merge_count(self,copy,lo,hi,tmp) -> int:
        #
        if lo==hi:return 0 #只有一个元素,一定有序,一定非逆序数
        #  
        mid=lo+(hi-lo)//2 #解决整形溢出问题
        n1=self.sort_merge_count(copy,lo,mid,tmp)
        n2=self.sort_merge_count(copy,mid+1,hi,tmp)
        #优化-已经有序
        if copy[mid]<=copy[mid+1]:
            return n1+n2
        n3=self.merge(copy,lo,mid,hi,tmp)
        #
        return n1+n2+n3
    #copy[left,mid],copy[mid+1,right]已经排好序 
    def merge(self,copy,lo,mid,hi,tmp) -> int:
        #
        for i in range(lo,hi+1):
            tmp[i]=copy[i]
        #
        i=k=lo
        j=mid+1
        count=0
        while 0<=k<=hi: #key
            if i==mid+1:
                copy[k]=tmp[j]
                j+=1
            elif j==hi+1:
                copy[k]=tmp[i]
                i+=1
            elif tmp[i]<=tmp[j]: #=:保证稳定排序
                copy[k]=tmp[i]
                i+=1
            else: 
                copy[k]=tmp[j]
                j+=1
                count+=mid-i+1 #key:利用部分数组的有序性
            k+=1
        return count

lc 315:https://leetcode.cn/problems/count-of-smaller-numbers-after-self/
提示:
1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4

class Solution:
    def countSmaller(self, nums: List[int]) -> List[int]:
        #nums->index tmp->tmpindex
        n=len(nums)
        self.index=[i for i in range(n)]
        self.tmp=[0]*n
        self.tmpindex=[0]*n #key:绑定元素和对应的索引
        #o(n)
        self.res=[0]*n
        self.sort_merge(nums,0,n-1)
        return self.res
        
    
    #o(nlogn):分治 
    def sort_merge(self, nums,lo,hi) -> None:
        #递归终止条件:最小子问题,无法继续分解
        if lo==hi:return 
        #
        mid=lo+(hi-lo)//2
        self.sort_merge(nums,lo,mid)
        self.sort_merge(nums,mid+1,hi)
        self.merge(nums,lo,mid,hi)
    #归并
    def merge(self, nums,lo,mid,hi) -> None:
        #
        for i in range(lo,hi+1):
            self.tmp[i]=nums[i]
            self.tmpindex[i]=self.index[i]
        #
        i=lo
        j=mid+1
        for k in range(lo,hi+1):
            if i==mid+1: #key
                nums[k]=self.tmp[j]
                self.index[k]=self.tmpindex[j]
                j+=1
            elif j==hi+1: #key
                nums[k]=self.tmp[i]
                self.index[k]=self.tmpindex[i]
                self.res[self.tmpindex[i]]+=(j-mid-1)
                i+=1
            elif self.tmp[i]<=self.tmp[j]:
                nums[k]=self.tmp[i]
                self.index[k]=self.tmpindex[i]
                self.res[self.tmpindex[i]]+=(j-mid-1) #key优化:i-mid-1:比当前元素小的后面元素的个数
                i+=1
            else:
                nums[k]=self.tmp[j]
                self.index[k]=self.tmpindex[j]
                j+=1

lc 327:https://leetcode.cn/problems/count-of-range-sum/
提示:
1 <= nums.length <= 10^5
-2^31 <= nums[i] <= 2^31 - 1
-10^5 <= lower <= upper <= 10^5
题目数据保证答案是一个 32 位 的整数

#问题转化(前缀和):查找[i,j]对使得: prefixSum[j] - prefixSum[i] ∈ [lower,upper]找到所有符合条件的[i,j]对,其中i!=j
#排序不影响结果:组间是独立的,不影响的
class Solution:
    def countRangeSum(self, nums: List[int], lower: int, upper: int) -> int:
        #前缀和
        n=len(nums)
        prefixsum=[0]*(n+1)
        for i in range(1,n+1):
            prefixsum[i]=prefixsum[i-1]+nums[i-1]
        #
        self.lower=lower
        self.upper=upper
        self.tmp=[0]*(n+1)
        return self.sort_merge(prefixsum,0,n)

    #o(nlogn):分治 
    def sort_merge(self, nums,lo,hi) -> int:
        #递归终止条件:最小子问题,无法继续分解
        if lo==hi:return 0
        #
        mid=lo+(hi-lo)//2
        n1=self.sort_merge(nums,lo,mid)
        n2=self.sort_merge(nums,mid+1,hi)
        #nums[left,mid],nums[mid+1,right]已排序
        count=0
        i=lo
        l=r=mid+1
        while i<=mid:
            while l<=hi and (nums[l]-nums[i])<self.lower:l+=1 #第一个>=lower
            while r<=hi and (nums[r]-nums[i])<=self.upper:r+=1 #第一个>upper
            count+=(r-l)
            i+=1
        #
        self.merge(nums,lo,mid,hi)
        #左半合并过程的统计(最小子问题)+右半合并过程的统计(最小子问题)+左半右半整体合并过程的统计
        return n1+n2+count
    #归并
    def merge(self, nums,lo,mid,hi) -> int:
        #
        for i in range(lo,hi+1):
            self.tmp[i]=nums[i]
        #
        i=lo
        j=mid+1
        for k in range(lo,hi+1):
            if i==mid+1: #key
                nums[k]=self.tmp[j]
                j+=1
            elif j==hi+1: #key
                nums[k]=self.tmp[i]
                i+=1
            elif self.tmp[i]<=self.tmp[j]:
                nums[k]=self.tmp[i]
                i+=1
            else:
                nums[k]=self.tmp[j]
                j+=1

lc 493:https://leetcode.cn/problems/reverse-pairs/
注意:
给定数组的长度不会超过50000。
输入数组中的所有数字都在32位整数的表示范围内。

class Solution:
    def reversePairs(self, nums: List[int]) -> int:
        n=len(nums)
        self.tmp=[0]*n
        return self.sort_merge(nums,0,n-1)

    #o(nlogn):分治 
    def sort_merge(self, nums,lo,hi) -> int:
        #递归终止条件:最小子问题,无法继续分解
        if lo==hi:return 0
        #
        mid=lo+(hi-lo)//2
        n1=self.sort_merge(nums,lo,mid)
        n2=self.sort_merge(nums,mid+1,hi)
        #nums[left,mid],nums[mid+1,right]已排序
        count=0
        i=lo
        j=mid+1
        while i <= mid:
            while j <= hi and (nums[i]-2 * nums[j])>0 : j += 1 #第一个不满足的->前面都满足
            count += (j - mid - 1)#i-mid-1:满足条件的后面元素的个数
            i += 1
        #
        self.merge(nums,lo,mid,hi)
        #左半合并过程的统计(最小子问题)+右半合并过程的统计(最小子问题)+左半右半整体合并过程的统计
        return n1+n2+count
    #归并
    def merge(self, nums,lo,mid,hi) -> int:
        #
        for i in range(lo,hi+1):
            self.tmp[i]=nums[i]
        #
        i=lo
        j=mid+1
        for k in range(lo,hi+1):
            if i==mid+1: #key
                nums[k]=self.tmp[j]
                j+=1
            elif j==hi+1: #key
                nums[k]=self.tmp[i]
                i+=1
            elif self.tmp[i]<=self.tmp[j]:
                nums[k]=self.tmp[i]
                i+=1
            else:
                nums[k]=self.tmp[j]
                j+=1

lc 50 【剑指 16】:https://leetcode.cn/problems/powx-n/
提示:
-100.0 < x < 100.0
-2^31 <= n <= 2^31-1
-10^4 <= xn <= 10^4

#快速幂+递归
#o(logn),o(logn)
class Solution:
    def myPow(self, x: float, n: int) -> float:
        if n<0:
            x=1/x
            n=-n
        return self.quickpow(x,n)

    #递归:O(logn),o(logn)
    def quickpow(self,x,n)->float:
        #
        if n==0:return 1
        if n==1:return x
        #
        mid=n//2
        y=self.quickpow(x,mid)
        #
        return y*y if n%2==0 else x*y*y
        
#优化-结合位运算
class Solution:
    def myPow(self, x: float, n: int) -> float:
        #
        if n<0:
            x=1/x
            n=-n
        #o(32),o(1)
        res=1
        while n!=0:
            if n&1==1 :res*=x #非零位,对结果影响
            #更新
            x*=x #x^2,x^4,x^8......
            n>>=1
        #
        return res

快速排序 - 分区逻辑的应用
未处理区域[great,hi]
二项切分:[<=pivot][>pivot]
在这里插入图片描述
三项切分:[<pivot][=pivot][>pivot]
在这里插入图片描述

lc 75【top100】:https://leetcode.cn/problems/sort-colors/
提示:
n == nums.length
1 <= n <= 300
nums[i] 为 0、1 或 2
进阶:
你可以不使用代码库中的排序函数来解决这道题吗?
你能想出一个仅使用常数空间的一趟扫描算法吗?

#方案一:计数排序:o(n),o(1)
class Solution:
    def sortColors(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        #计数:o(n),o(1)
        count=[0]*3
        for i in range(len(nums)):
            count[nums[i]]+=1
        #排序
        k=0
        for i in range(3):
            n=count[i]
            for j in range(n):
                nums[k]=i
                k+=1
        #
        return nums
        
#方案二:三路快排类比 [==0][==1][==2]
class Solution:
    def sortColors(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        #o(1)
        zero=0
        two=len(nums)-1
        i=0
        #o(n)
        pivot=1
        while i<=two:
            if nums[i]<pivot:
                nums[i],nums[zero]=nums[zero],nums[i]
                i+=1
                zero+=1
            elif nums[i]>pivot:
                nums[i],nums[two]=nums[two],nums[i]
                two-=1
            else:i+=1
        #
        return nums

lc 179【剑指 45】:https://leetcode.cn/problems/largest-number/
提示:
1 <= nums.length <= 100
0 <= nums[i] <= 10^9

import random

class largestNumkey(str):
    def __lt__(x,y):
        return x+y>y+x #富比较

class Solution:
    def largestNumber(self, nums: List[int]) -> str:
        largestNum=''.join(sorted(map(str,nums),key=largestNumkey))
        return largestNum if largestNum[0]!='0'else '0'

lc 56【剑指 74】:区间合并
https://leetcode.cn/problems/merge-intervals/
提示:
1 <= intervals.length <= 10^4
intervals[i].length == 2
0 <= starti <= endi <= 10^4
【计算之魂 11章】

class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        # 根据 start_i 进行排序
        intervals.sort(key=lambda x: x[0])
        merged = [intervals[0]]
        for interval in intervals:
            start, end = interval
            # 如果列表为空,或者当前区间与上一区间不重合,直接添加
            if merged[-1][1] < start:
                merged.append(interval)
            # 否则的话,我们就可以与上一区间进行合并
            else:
                merged[-1][1] = max(merged[-1][1], end)
        return merged

lc 57 :https://leetcode.cn/problems/insert-interval/
提示:
0 <= intervals.length <= 10^4
intervals[i].length == 2
0 <= intervals[i][0] <= intervals[i][1] <= 10^5
intervals 根据 intervals[i][0] 按 升序 排列
newInterval.length == 2
0 <= newInterval[0] <= newInterval[1] <= 10^5

#方案一:
class Solution:
    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
        #
        interval=intervals
        interval.append(newInterval)
        if len(interval)==0:return []
        #o(n),o(1)
        output=[]
        interval.sort(key=lambda x:x[0])
        output.append(interval[0]) #排序后的
        for i in range(1,len(interval)):
            curl,curr=interval[i][0],interval[i][1]
            if curl<=output[-1][1]: #重叠
                output[-1][1]=max(output[-1][1],curr)
            else:output.append(interval[i])
        #
        return output
#方案二:
class Solution:
    def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]:
        #o(n),o(1)
        i=0
        res=[]
        while i<len(intervals) and intervals[i][1]<newInterval[0]:
            res.append(intervals[i])
            i+=1
        #
        while i<len(intervals) and intervals[i][0]<=newInterval[1]:#重叠
            newInterval[0]=min(intervals[i][0],newInterval[0])
            newInterval[1]=max(intervals[i][1],newInterval[1])
            i+=1
        res.append(newInterval)
        #
        while i<len(intervals):
            res.append(intervals[i])
            i+=1
        #
        return res

lc 905:https://leetcode.cn/problems/sort-array-by-parity/
提示:
1 <= nums.length <= 5000
0 <= nums[i] <= 5000

#方案一:暴力解法-O(n),o(n)
class Solution:
    def sortArrayByParity(self, nums: List[int]) -> List[int]:
        #
        res=[0]*len(nums)
        #
        left=0
        right=len(nums)-1
        for i in range(len(nums)):
            if nums[i]%2==0:
                res[left]=nums[i]
                left+=1
            else:
                res[right]=nums[i]
                right-=1
        #
        return res
#方案二:类比二向快排o(n),o(1)
class Solution:
    def sortArrayByParity(self, nums: List[int]) -> List[int]:
        #o(n),o(1)
        double=single=0
        while single<=len(nums)-1:
            if nums[double]%2 > nums[single]%2: #左奇右偶,换位
                nums[double],nums[single]=nums[single],nums[double]
            if nums[double]%2==0:double+=1
            #     double+=1
            # elif nums[single]%2==0:double+=1 #偶+偶
            # #其他:偶+奇
            single+=1
        #
        return nums

#方案三:优化-减少交换次数
class Solution:
    def sortArrayByParity(self, nums: List[int]) -> List[int]:
        #o(n),o(1)
        left=0
        right=len(nums)-1
        while left<=right:
            if nums[left]%2 > nums[right]%2: #左奇右偶,换位
                nums[left],nums[right]=nums[right],nums[left]
            if nums[left]%2==0:left+=1
            if nums[right]%2==1:right-=1
        #
        return nums

lc 922:https://leetcode.cn/problems/sort-array-by-parity-ii/
提示:
2 <= nums.length <= 2 * 10^4
nums.length 是偶数
nums 中一半是偶数
0 <= nums[i] <= 1000
进阶:可以不使用额外空间解决问题吗?

#双指针思路
class Solution:
    def sortArrayByParityII(self, nums: List[int]) -> List[int]:
        #o(1)
        i=0
        j=1
        #o(n)
        while i<=len(nums)-1:
            if nums[i]%2 ==1:
                while nums[j]%2 !=0:j+=2
                nums[i],nums[j]=nums[j],nums[i]
            i+=2
        #
        return nums

lc 1365:https://leetcode.cn/problems/how-many-numbers-are-smaller-than-the-current-number/
提示:
2 <= nums.length <= 500
0 <= nums[i] <= 100

#方案一:超时(快排/归并)
class Solution:
    def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]:
        #绑定
        n=len(nums)
        data=[[0]*2]*n
        for i in range(n):
            data[i][0]=nums[i]
            data[i][1]=i
        #o(nlogn),o(n)
        data.sort(key=lambda x:x[0])
        i=0
        prev=-1
        res=[0]*n
        while i <n:
            if prev==-1 or data[i]!=data[i-1]:
                prev=i
            res[i]=prev
        #
        return res
        
#计数排序-o(n),o(n)
class Solution:
    def smallerNumbersThanCurrent(self, nums: List[int]) -> List[int]:
        #o(n)
        counts=[0]*(101)
        for num in nums:
            counts[num]+=1
        for i in range(1,101):
            counts[i]+=counts[i-1]
        #o(n)
        res=[0]*len(nums)
        for i in range(len(nums)):
            res[i]=counts[nums[i]-1] if nums[i] !=0 else 0 #key
        #
        return res

lc 164:https://leetcode.cn/problems/maximum-gap/
提示:
1 <= nums.length <= 10^5
0 <= nums[i] <= 10^9

#方案一:桶排序
#平均间距-gap=(max - min)/ (nums.length- 1)
#最大的间距肯定不会小于gap
'''
key:将间距小于gap的所有元素放在一个桶中
bucketNum = nums.length   ∵有可能所有元素间间距都为gap
bucketld =(num -min)/ gap
'''
#桶间有序
import math
class Solution:
    def maximumGap(self, nums: List[int]) -> int:
        n=len(nums)
        if n < 2: return 0  
        #o(n):初始桶 
        buckets_num=n
        INTMAX,INTMIN=2**31-1,-2**31
        buckets=[[INTMAX,INTMIN] for _ in range(buckets_num)] #key
        #o(n:)定义桶
        max_num,min_num=max(nums),min(nums) #变量化(优化)
        if max(nums)==min(nums):return 0
        gap=int(math.ceil((max_num-min_num)/(n-1)))
        for num in nums:
            bucket_id = (num - min_num) // gap
            buckets[bucket_id][0] = min(buckets[bucket_id][0], num)
            buckets[bucket_id][1] = max(buckets[bucket_id][1], num)
        #求最大间隔
        max_gap=0
        prevbucketmax=min_num
        for bucket in buckets:
            if bucket[0]==INTMAX:continue #注 
            max_gap=max(max_gap,bucket[0]-prevbucketmax)
            prevbucketmax=bucket[1]
        return max_gap

#方案二:基数排序-适合数字范围很大(分别比较个位,十位......)
#核心:利用计数排序
class Solution:
    def maximumGap(self, nums: List[int]) -> int:
        n=len(nums)
        data=self.sort(nums)
        #
        gap=0
        for i in range(1,n):
            gap=max(data[i]-data[i-1],gap)
        #
        return gap
 
    #o(n),o(n)
    def sort(self,data):
        #位数
        n=len(data)
        maxnum=0
        for i in range(n):
            maxnum=max(maxnum,data[i])
        exp=1
        while maxnum//exp !=0:
            self.countSort(data,exp)
            exp*=10
        #
        return data

    def countSort(self,data,exp):
        n=len(data)
        count=[0]*10
        #
        for i in range(n):
            count[(data[i]//exp)%10]+=1
        for i in range(1,10):
            count[i]+=count[i-1]
        #
        res=[0]*n
        for i in range(n):
            k=count[(data[i]//exp)%10]-1
            res[k]=data[i]
            count[(data[i]//exp)%10]-=1
        #
        for i in range(n):
            data[i]=res[i]                    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值