[每日一刷] (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)):
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)
res = []
for i in nums:
temp = tree.query(i-1 )
res.append(temp)
tree.modify(i)
return res