(Leetcode) 计算右侧小于当前元素的个数 - Python实现

题目:计算右侧小于当前元素的个数
给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是  nums[i] 右侧小于 nums[i] 的元素的数量。
示例:
输入: [5,2,6,1],输出: [2,1,1,0] 
解释:
5 的右侧有 2 个更小的元素 (2 和 1).
2 的右侧仅有 1 个更小的元素 (1).
6 的右侧有 1 个更小的元素 (1).
1 的右侧有 0 个更小的元素.

-----------------------------------------------------------------------------

解法1:传统思路,逐个遍历,超时。

class Solution(object):
    def countSmaller(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        counts = []
        for i in range(len(nums)):

            count = 0
            for j in range(i+1, len(nums)):
                if nums[i] > nums[j]:
                    count += 1
            counts.append(count)
        return counts

解法2#:分治算法,利用归并排序的思路。

(了解归并排序算法可以看我之前写的博客:https://blog.csdn.net/weixin_42077402/article/details/93079385)

思路:要计算某个元素后面比它小的个数,可以统计在归并排序过程中,合并两个有序数组时,从右侧转到左侧元素nums[i] 的个数(即右侧比 左侧元素nums[i] 小的个数)。

class Solution(object):
    def countSmaller(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        vec = []
        # 记录每个元素的下标
        for index, num in enumerate(nums):
            vec.append([num, index])

        # 初始化结果数组
        self.counts = [0] * len(nums)

        # 构造归并函数
        def merge_sort(nums, L, R):
            if L >= R:
                return
            mid = L + (R-L)//2
            merge_sort(nums, L, mid)
            merge_sort(nums, mid + 1, R)

            i, j = L, mid + 1
            # j-mid-1 相当于j到j=mid+1时中间的元素个数
            while i <= mid and j <= R:
                if nums[i][0] <= nums[j][0]:
                    # nums[i][1] 为初始数组中下标
                    self.counts[nums[i][1]] += j-mid-1  # j-mid-1 相当于j到j=mid+1时中间的元素个数
                    i += 1
                else:
                    j += 1

            # 左边数组是排序好的,故下标为i以后的元素均需要加
            for k in range(i, mid + 1):
                self.counts[nums[k][1]] += j - mid - 1

            # 排序
            nums[L:R + 1] = sorted(nums[L:R + 1])

        merge_sort(vec, 0, len(nums)-1)

        return self.counts

解法3#:利用二叉树搜索得出。

class Tree(object):
    def __init__(self, val):
        self.val = val
        self.left = None
        self.right = None
        self.num = 1
 
 
class Solution(object):

    def countSmaller(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        def insert(root, val, temp):
            if root.val < val:
                temp += root.num
                if root.right is not None:
                    root.right, temp = insert(root.right, val, temp)
                else:
                    root.right = Tree(val)
            else:
                root.num += 1
                if root.left is not None:
                    root.left, temp = insert(root.left, val, temp)
                else:
                    root.left = Tree(val)
            return root, temp
 
        n = len(nums)
        if n == 0:
            return []
        root = Tree(nums[-1])
        ret = [0]
        for i in range(n - 2, -1, -1):
            root, num = insert(root, nums[i], 0)
            ret.append(num)

        return ret[::-1]

参考:

https://blog.csdn.net/qq_33304418/article/details/90023149

https://blog.csdn.net/clelouch/article/details/80394665

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值