题目:计算右侧小于当前元素的个数
给定一个整数数组 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]
参考: