LeetCode排序算法

75、颜色分类,有三种值0、1、2需要将他们排序

思路与快排类似,用zero,two记录0、2的下标,使用i遍历数组,当找到0/2时将i与对应下标的nums交换

class Solution:
    def sortColors(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        def swap(nums,index1,index2):
            nums[index1],nums[index2]=nums[index2],nums[index1]
        n=len(nums)
        if n <2:
            return
        zero = 0
        two  = n
        i    = 0
        while i<two:
            if nums[i]==0:
                swap(nums, i, zero)
                i+=1
                zero+=1
            elif nums[i]==1:
                i+=1
            else:
                two-=1
                swap(nums, i, two)
                
        return nums  

88、合并有序数组

由于给出的是两个有序数组,在为结果数组添加数字的时候直接比较两个数组的最后一位即可插入数组。

详细思路参考:

作者:灵茶山艾府 链接:https://leetcode.cn/problems/merge-sorted-array/solutions/2385610/dao-xu-shuang-zhi-zhen-wei-shi-yao-dao-x-xxkp/ 来源:力扣

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        p1, p2, p = m - 1, n - 1, m + n - 1
        while p2 >= 0:  # nums2 还有要合并的元素
            # 如果 p1 < 0,那么走 else 分支,把 nums2 合并到 nums1 中
            if p1 >= 0 and nums1[p1] > nums2[p2]:
                nums1[p] = nums1[p1]  # 填入 nums1[p1]
                p1 -= 1
            else:
                nums1[p] = nums2[p2]  # 填入 nums2[p1]
                p2 -= 1
            p -= 1  # 下一个要填入的位置

LCR 170、交易逆序对的总数

使用分治算法,将数组切分,在每次和并的时候统计当前左数组和右数组之间逆序对的数量。

详解见链接

class Solution:
    def reversePairs(self, record: List[int]) -> int:
        def merge_sort(l, r):
            # 终止条件
            if l >= r: return 0
            # 递归划分
            m = (l + r) // 2
            res = merge_sort(l, m) + merge_sort(m + 1, r)
            # 合并阶段
            i, j = l, m + 1
            tmp[l:r + 1] = record[l:r + 1]
            for k in range(l, r + 1):
                if i == m + 1:
                    record[k] = tmp[j]
                    j += 1
                elif j == r + 1 or tmp[i] <= tmp[j]:
                    record[k] = tmp[i]
                    i += 1
                else:
                    record[k] = tmp[j]
                    j += 1
                    res += m - i + 1 # 统计逆序对
            return res
        
        tmp = [0] * len(record)
        return merge_sort(0, len(record) - 1)

作者:Krahets
链接:https://leetcode.cn/problems/shu-zu-zhong-de-ni-xu-dui-lcof/solutions/622496/jian-zhi-offer-51-shu-zu-zhong-de-ni-xu-pvn2h/

215、数组前k个最大的数

题目要求时间复杂度在O(n),使用了分治排序通过了。

以下是提交的代码:

class Solution:
    def findKthLargest(self, nums: list[int], k: int) -> int:
        n=len(nums)-1
        def mergesort(l,r):
            if l>=r:
                return 0
            m=(l+r)//2
            mergesort(l,m)
            mergesort(m+1,r)
            i,j=l,m+1
            tmp[l:r+1]=nums[l:r+1]
            for k in range(l,r+1):
                if i==m+1 :
                    nums[k]=tmp[j]
                    j+=1
                elif j==r+1 or tmp[i]<=tmp[j]:
                    nums[k]=tmp[i]
                    i+=1                    
                else: 
                    nums[k]=tmp[j]
                    j+=1
            return 0
        tmp=[0]*len(nums)
        mergesort(0,n) 
        ans=0
        for i in range(n,-1,-1):
            ans+=1
            if ans==k :
                return nums[i]

有个疑问是 for k 循环语句里的条件判断,如果写成

            for k in range(l,r+1):
                if i==m+1 or tmp[i]>=tmp[j]:
                    nums[k]=tmp[j]
                    j+=1
                else: 
                    nums[k]=tmp[i]
                    i+=1

会显示出错,超出了数组的索引 

需要将判断条件改成if i==m+1 or (j<=r and tmp[j]<tmp[i]) :

面试题 17.14 最小k个数

思路与上一题类似

class Solution:
    def smallestK(self, arr: List[int], k: int) -> List[int]:
        n=len(arr)-1
        temp=[0]*(n+1)
        def mergesort(l,r):
            if l>=r:
                return 0
            m=(l+r)//2
            mergesort(l,m)
            mergesort(m+1,r)

            i,j=l,m+1
            temp[l:r+1]=arr[l:r+1]
            for k in range(l,r+1):
                if i==m+1 or (j<=r and temp[j]<=temp[i]):
                    arr[k]=temp[j]
                    j+=1
                else:
                    arr[k]=temp[i]
                    i+=1
            return arr
        arr=mergesort(0,n)
        result=[]
        for i in range(k):
            result.append(arr[i])
        return result

1122、数组的相对排序

需要注意字典的处理

class Solution:
    def relativeSortArray(self, arr1: List[int], arr2: List[int]) -> List[int]:
        n1,n2=len(arr1),len(arr2)
        dic={}
        new_arr=[]
        result=[]
        for num in arr1:
            if num in arr2:
                if num in dic:
                    dic[num]+=1
                else:
                    dic[num]=1
            else:
                new_arr.append(num)
        for num in arr2:
            result=result+[num]*dic[num]
        new_arr.sort()
        return result+new_arr

 220、存在重复元素3 

需要在数组中查找窗口为indexDiff的子数组中是否有两个数的差的绝对值<=valueDiff

在思考的时候想到查找窗口这么回事,但是想不到如何处理其中的数,因为按暴力遍历的话会超时。看了题解后才想得到如何使用桶排序。使用字典进行存储,原数组的数按照大小分配到不同的桶:nth=nums[i]//(valueDiff+1),这样子只有同一个或相邻的桶中的数值满足差的绝对值的约束。

最后要记得保持窗口的长度为indexDiff+1

class Solution:
    def containsNearbyAlmostDuplicate(self, nums: List[int], indexDiff: int, valueDiff: int) -> bool:
        bucket=dict()
        for i in range(len(nums)):
            nth=nums[i]//(valueDiff+1)
            if nth in bucket:
                return True
            if nth-1 in bucket and abs(nums[i]-bucket[nth-1])<=valueDiff:
                return True
            if nth+1 in bucket and abs(nums[i]-bucket[nth+1])<=valueDiff:
                return True
            bucket[nth]=nums[i]       
            if i>=indexDiff:
                bucket.pop(nums[i-indexDiff]//(valueDiff+1))
        return False    

164、最大间距

想用桶排序,,被击穿了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值