📅  最后修改于: 2023-12-03 14:54:59.545000             🧑  作者: Mango
在一个整数数组 nums 中,对于每个 nums[i],请计算出它右侧比它大的元素数量。
示例:
输入:nums = [5,2,6,1] 输出:[2,1,1,0] 解释: 5 的右侧有 2 个比它大的数(6 和 44)。 2 的右侧仅有 1 个比它大的数(6)。 6 的右侧仅有 1 个比它大的数(44)。 1 的右侧没有比它大的数。
该问题可以用暴力求解,我们可以使用嵌套循环,对于每个数 check 所有的右侧元素是否比他大,如果是,那么 count++。
下面是 python3 的代码片段:
def countSmaller(nums):
counts = []
for i in range(len(nums)):
count = 0
current = nums[i]
for j in range(i+1, len(nums)):
if nums[j] > current:
count += 1
counts.append(count)
return counts
该算法的时间复杂度为 $O(n^2)$,不是最优解法,但是可以用来帮助我们更好地理解问题。
更高效的解法是使用归并排序算法。首先我们需要给 nums 数组排序,并记录每个数的原始下标。我们从数组的右侧开始遍历已排序的数,对于每个数,我们都可以用一个计数器记录其右侧比它大的元素数量,并将这个计数器赋值给结果数组 num_counts 中对应的位置。具体实现可以看下面的代码:
def countSmaller(nums):
def merge_sort(enum):
mid = len(enum) // 2
if mid:
left, right = merge_sort(enum[:mid]), merge_sort(enum[mid:])
for i in range(len(enum))[::-1]:
if not right or left and left[-1][1] > right[-1][1]:
smaller[left[-1][0]] += len(right)
enum[i] = left.pop()
else:
enum[i] = right.pop()
return enum
smaller = [0] * len(nums)
merge_sort(list(enumerate(nums)))
return smaller
在该版本中,我们使用了归并排序算法。我们首先将enumerate(nums)中的每个数变成一个有序的数对,其中第一个元素是原数组nums中的数对应的下标,第二个元素是原数组nums中的数。我们然后按照 数组中第二个元素的大小 对整个数组排序。在排序过程中,我们对于每个数 check 排序后的数组的右侧,如果右侧的数比它大,那么这个数的下标对应的结果数组 smaller 中值就应该加一。 最后我们返回 smaller 数组。
这个算法的时间复杂度为 $O(n \log n)$,因为我们使用了归并排序算法,最坏情况下需要进行的操作次数的上界是 $n \log n$,所以时间复杂度是 $O(n \log n)$。