Count of Smaller Number
Question
Give you an integer array (index from 0 to n-1, where n is the size of this array, value from 0 to 10000) and an query list. For each query, give you an integer, return the number of element in the array that are smaller that the given integer.
Have you met this question in a real interview? Yes
Example
For array [1,2,7,8,5]
, and queries [1,8,5]
, return [0,4,2]
Note We suggest you finish problem Segment Tree Build and Segment Tree Query II first.
Challenge Could you use three ways to do it.
- Just loop
- Sort and binary search
- Build Segment Tree and Search.
Thoughts
1.just loop
O(n^2)
- sort and binary search
O(nlogn + logn)
- segment tree
O(n + logn + logn)
Solution
SegmentTree
class Solution:
"""
@param A: A list of integer
@return: The number of element in the array that
are smaller that the given integer
"""
def countOfSmallerNumber(self, A, queries):
# write your code here
segT = SegmentTree()
root = segT.build(0, 10000)
for num in A:
segT.modify(root, num, 1)
result = []
for q in queries:
res = 0
if q > 0:
res = segT.query(root, 0, q - 1)
result.append(res)
return result
"""
class SegmentTreeNode:
def __init__(self, start, end, count):
self.start = start
self.end = end
self.count = count
self.left, self.right = None, None
"""
class SegmentTree:
def __init__(self):
self.root = None
def build(self, start, end):
if start > end:
return None
root = SegmentTreeNode(start, end, 0)
if start < end:
mid = (start + end) / 2
root.left = self.build(start, mid)
root.right = self.build(mid+1, end)
else:
root.count = 0
return root
def query(self, root, start, end):
if not root:
return 0
rStart = root.start
rEnd = root.end
if (rStart > end) or ( rEnd < start):
return 0
#should be >= and <=
#if query range if larger than the segment tree range, just return the count
if rStart >= start and rEnd <= end:
return root.count
leftCount = 0
rightCount = 0
mid = (rStart + rEnd) / 2
if start <= mid:
if end > mid:
#some range are in right part
leftCount = self.query(root.left, start, mid)
else:
leftCount = self.query(root.left, start, end)
if mid < end:
if start <= mid:
#some range are in left part
#right part should start with mid + 1
rightCount = self.query(root.right, mid + 1, end)
else:
rightCount = self.query(root.right, start, end)
return leftCount + rightCount
def modify(self, root, index, value):
if root.start == index and root.end == index:
root.count += value
return
mid = (root.start + root.end) / 2
if root.start <= index and index <= mid:
self.modify(root.left, index, value)
elif root.end >= index and index > mid:
self.modify(root.right, index, value)
root.count = root.left.count + root.right.count
binary search的方法
找到每个Num在数组中的index
A = sorted(A)
results = []
for q in queries:
results.append(self.countSmaller(A, q))
return results
def countSmaller(self, A, q):
# find the first number in A >= q
if len(A) == 0 or A[-1] < q:
return len(A)
start, end = 0, len(A) - 1
while start + 1 < end:
mid = (start + end) / 2
if A[mid] < q:
start = mid
else:
end = mid
if A[start] >= q:
return start
if A[end] >= q:
return end
return end + 1