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

Hard

方法一(暴力)(TLE)

思路

首先想到的方法是暴力解,题目没有给出数据规模。但是作为Hard题,暴力解大概率会超时。

尝试一下,果不其然,TLE

代码

python3

class Solution:
  def countSmaller(self, nums: List[int]) -> List[int]:
    r = []
    for i in range(len(nums)):
      t = 0
      for j in range(i, len(nums)):
        if nums[j] < nums[i]:
          t += 1
      r.append(t)
    return r

方法二(归并排序)

阅读大佬解法,获得新思路,使用归并排序求解

这道题本质上说是求逆序数,而逆序数归并排序的副产物

话不多说,先学一波归并排序:

https://www.interviewbit.com/tutorial/merge-sort-algorithm/ https://www.jianshu.com/p/3ad5373465fd https://www.cnblogs.com/chengxiao/p/6194356.html

学习了归并排序之后再回过头看这道题

补充说明

以下视屏,讲的很清晰,看两遍就能理解了

参考 happygrilzt

LeetCode 315 Count of Smaller Numbers After Self 中文解释 Chinese Version

以上,尝试写一下代码,AC!

代码

python3

class Solution:
  def merge(self,nums, indexes, left, right, res):
    i = 0
    j = 0
    r = []
    rightCount = 0
    while i < len(left) and j < len(right):
      if nums[left[i]] <= nums[right[j]]:
        res[left[i]] += rightCount
        r.append(left[i])
        i += 1
      else:
        rightCount += 1
        r.append(right[j])
        j += 1
    while i < len(left):
      res[left[i]] += rightCount
      r.append(left[i])
      i += 1
    while j < len(right):
      r.append(right[j])
      j += 1
    return r

  def mergeSort(self,nums, indexes, start ,end, res):
    if end-start <= 1:
      return indexes[start:end]
    mid = start + (end-start) // 2
    left = self.mergeSort(nums, indexes, start ,mid, res)
    right = self.mergeSort(nums, indexes, mid , end, res)
    return self.merge(nums,indexes,left,right, res)

  def countSmaller(self, nums: List[int]) -> List[int]:
    indexes = [ i for i in range(len(nums)) ]
    res = [ 0 for i in range(len(nums)) ]
    r = self.mergeSort(nums,indexes, 0,len(nums), res) 
    return res