每日一刷-Count of Smaller Numbers After Self

[每日一刷] (Count of Smaller Numbers After Self)


You are given an integer array nums and you have to return a new counts array.
The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i].

Example:
Given nums = [5, 2, 6, 1]
Return the array [2, 1, 1, 0]

解题思路


这题其实又是一个有关区间的题,每次都找当前值后面有多少个比它小的数。因此马上可以想到用线段树。
这道题其实就是值线段树的简单应用,线段树结点中存储一个区间内有多少个值,然后每次查询后修改线段树。
这题主要就是各种边界条件比较多,下次要注意。

Python:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
"""
时间复杂度 O(nlog(n))
"""
class SegmentTree(object):
def __init__(self, d, nums, left, right):
self.left, self.right = left, right
self.val = 0
self.mid = self.left + (self.right - self.left) / 2
self.c1 = self.c2 = None
if self.left == self.right:
self.val = d[self.left]
else:
self.c1 = SegmentTree(d, nums, self.left, self.mid)
self.c2 = SegmentTree(d, nums, self.mid+1, self.right)
self.val = self.c1.val + self.c2.val
def query(self, right):
if right < self.left:
return 0
if self.right == self.left:
return self.val
if self.right == right:
return self.val
else:
if right <= self.mid:
return self.c1.query(right)
else:
return self.c1.query(self.mid) + self.c2.query(right)
def modify(self, index):
if self.left == self.right and self.left == index:
self.val -= 1
else:
if index <= self.mid:
self.c1.modify(index)
else:
self.c2.modify(index)
self.val = self.c1.val + self.c2.val
class Solution(object):
def countSmaller(self, nums):
"""
:type nums: List[int]
:rtype: List[int]
"""
if nums == []:
return []
left, right = min(nums), max(nums)
for i in xrange(len(nums)): # deal with numbers below zero.
nums[i] -= left
right -= left
d = [0 for i in xrange(right+1)]
for i in nums:
d[i] += 1
tree = SegmentTree(d, nums, 0, right) # build segment tree.
res = []
for i in nums:
temp = tree.query(i-1)
res.append(temp)
tree.modify(i) # modify the tree after each query
return res