Give you an integer array (index from 0 to n-1, where n is the size of this array, data value from 0 to 10000) . For each element Ai
in the array, count the number of element before this element Ai
is smaller than it and return count number array.
Example
Example 1:
Input:
[1,2,7,8,5]
Output:
[0,1,2,3,2]
Example 2:
Input:
[7,8,2,1,3]
Output:
[0,1,0,0,2]
Clarification
Before you do this, we suggest you complete the following three questions: Segment Tree Build, Segment Tree Query II,and Count of Smaller Number before itself I 。
思路:用segment tree来记录当前点之前的所有的count,并且维护线段树的count,首先建立一个空的线段树,然后每次遇见一个数,把他的index node count值++,最后 querySum (0, A[i]-1)的线段count即可,注意一定要做一个特殊例子判断,就是A[i] == 0,比0小的数没有,因为数组是[0,10000] 的数,所以,没有,list直接加0,但是0这个node的count还是要++,因为他是其他比0大的数的小于的count;
public class Solution {
/**
* @param A: an integer array
* @return: A list of integers includes the index of the first number and the index of the last number
*/
public List<Integer> countOfSmallerNumberII(int[] A) {
List<Integer> list = new ArrayList<>();
SegmentTree segmentTree = new SegmentTree(10001);
for(int num: A) {
if(num == 0) {
list.add(0);
} else {
list.add(segmentTree.querySum(0, num - 1));
}
segmentTree.add(num, 1);
}
return list;
}
public class SegmentTreeNode {
public int start, end;
public int sum;
public SegmentTreeNode left, right;
public SegmentTreeNode (int start, int end) {
this.start = start;
this.end = end;
this.sum = 0;
this.left = null;
this.right = null;
}
}
public class SegmentTree {
public SegmentTreeNode root;
public int size;
public SegmentTree (int size) {
this.size = size;
this.root = buildTree(0, size - 1);
}
public SegmentTreeNode buildTree(int start, int end) {
if(start > end) {
return null;
}
SegmentTreeNode node = new SegmentTreeNode(start, end);
if(start == end) {
return node;
}
int mid = start + (end - start) / 2;
node.left = buildTree(start, mid);
node.right = buildTree(mid + 1, end);
return node;
}
public int querySum(int start, int end) {
return querySumHelper(root, start, end);
}
public int querySumHelper(SegmentTreeNode node, int start, int end) {
if(node.start == start && node.end == end) {
return node.sum;
}
int mid = node.start + (node.end - node.start) / 2;
// node.start..........mid.......node.end;
// start.......end;
int leftsum = 0, rightsum = 0;
if(start <= mid) {
leftsum = querySumHelper(node.left, start, Math.min(mid, end));
}
if(mid + 1 <= end) {
rightsum = querySumHelper(node.right, Math.max(mid + 1, start), end);
}
return leftsum + rightsum;
}
public void add(int index, int value) {
addHelper(root, index, value);
}
public void addHelper(SegmentTreeNode node, int index, int value) {
if(node.start == node.end && node.end == index) {
node.sum += value;
return;
}
int mid = node.start + (node.end - node.start) / 2;
if(index <= mid) {
addHelper(node.left, index, value);
}
if(mid + 1 <= index) {
addHelper(node.right, index, value);
}
node.sum = node.left.sum + node.right.sum;
}
}
}