(力扣每日一题)计算右侧小于当前元素的个数

计算右侧小于当前元素的个数

给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。

(力扣每日一题)计算右侧小于当前元素的个数_第1张图片
解题思路
方法一:暴力求解:通过两层循环,一一比较,遍历所有情况。复杂度为o(n^2)。
方法二:通过二分查找改进暴利求解
在第一轮的基础上第二轮的遍历的复杂度。也就是把n减少到一个复杂度更小的情况,一般选择o(logn),即可用二分法快速找到有几个比当前元素小,这就现实了从n降阶到logn。
优化关键点
(1)对应每个单个元素,有一个单调的(排好序的)list储存所有在他右边的元素。这个list用于后面使用二分检索来找小于该元素的元素的个数。(2)快速使用二分检索。
主要操作步骤:
1、无论nums里面前面的数字怎么排布,最后一个元素对应的输出一定是0。因为他的右边没有别的元素可以给他比较。
2、nums从右往左输入。即方便不断给sorted_nums的list添加新元素。sorted_nums为排序好的储存当前素有右边元素的list。
3、实现排序的方法是用bisect.insort将当前的元素放到sorted_nums中间对应的排序下的位置。
4、对于每个元素而言,右边的所有元素已经存放在sorted_nums中,并且排好序。
5、可以直接使用bisect.bisect_left找到对应的元素在sorted_nums的下标。他的下标表示为在sorted_nums中比他小的元素的个数。把其一次添加到ans中去。
6、由于sorted_nums是从右往左添加的,ans添加index的顺序也是从右往左的。所有最后返回的时候要重新颠倒回来。
算法分析:
时间复杂度:第一轮循环遍历所有元素o(n),第二轮循环使用二分检索o(logn)。综合来说是o(nlogn)。
空间复杂度:需要创建一个sorted_nums来记录排序好的右边元素。所以是:o(n)。

class Solution:
    def countSmaller(self, nums: List[int]) -> List[int]:
        if not nums: return []
        
        sorted_nums = []
        ans = []
       ## 二分查找bisect模块,Python自带的函数
        for n in nums[::-1]:
            index = bisect.bisect_left(sorted_nums,n)
            bisect.insort(sorted_nums,n)
            ans.append(index)
        return ans[::-1]

你可能感兴趣的:((力扣每日一题)计算右侧小于当前元素的个数)