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 than the given integer.
Example
Example 1:
Input: array =[1,2,7,8,5] queries =[1,8,5]
Output:[0,4,2]
Example 2:
Input: array =[3,4,5,8] queries =[2,4]
Output:[0,1]
Challenge
Could you use three ways to do it.
- Just loop
- Sort and binary search
- Build Segment Tree and Search.
Notice
We suggest you finish problem Segment Tree Build and Segment Tree Query II first.
思路:因为A已经给定了,所以可以用统计好的数组B来build tree;建立树是O(N),查询是mlog(n)
public class Solution {
/**
* @param A: An integer array
* @param queries: The query list
* @return: The number of element in the array that are smaller that the given integer
*/
public List<Integer> countOfSmallerNumber(int[] A, int[] queries) {
List<Integer> list = new ArrayList<>();
int[] B = new int[10001];
for(int num: A) {
B[num]++;
}
SegmentTree segmentTree = new SegmentTree(B);
for(int query: queries) {
list.add(segmentTree.query(0, query - 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[] A) {
this.size = A.length;
this.root = buildTree(A, 0, size - 1);
}
public SegmentTreeNode buildTree(int[] A, int start, int end) {
if(start > end) {
return null;
}
SegmentTreeNode node = new SegmentTreeNode(start, end);
if(start == end) {
node.sum = A[start];
return node;
}
int mid = start + (end - start) / 2;
node.left = buildTree(A, start, mid);
node.right = buildTree(A, mid + 1, end);
node.sum = node.left.sum + node.right.sum;
return node;
}
public int query(int start, int end) {
return queryHelper(root, start, end);
}
public int queryHelper(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;
int leftsum = 0, rightsum = 0;
// node.start........mid.........node.end;
// start......end;
if(start <= mid) {
leftsum = queryHelper(node.left, start, Math.min(mid, end));
}
if(mid + 1 <= end) {
rightsum = queryHelper(node.right, Math.max(mid + 1, start), end);
}
return leftsum + rightsum;
}
}
}
这里可以稍微优化一下,可以省去一个10001size的数组;把modify稍微改一下,变成add,建立一个空segment tree,然后一点点的往里面modify添加数据;建立数是O(N),查询是mlog(n)
public class Solution {
/**
* @param A: An integer array
* @param queries: The query list
* @return: The number of element in the array that are smaller that the given integer
*/
public List<Integer> countOfSmallerNumber(int[] A, int[] queries) {
List<Integer> list = new ArrayList<Integer>();
SegmentTree tree = new SegmentTree(10001);
for(int i : A) {
tree.add(i, 1);
}
for(int i : queries) {
if(i == 0) {
list.add(0);
} else {
list.add(tree.querySum(0, i -1));
}
}
return list;
}
private class SegmentTreeNode {
public int start, end;
public SegmentTreeNode left, right;
public int sum;
public SegmentTreeNode(int start, int end) {
this.start = start;
this.end = end;
this.sum = 0;
this.left = null;
this.right = null;
}
}
private class SegmentTree {
private SegmentTreeNode root;
private int size;
public SegmentTree(int size) {
this.size = size;
this.root = buildTree(0, size - 1);
}
private SegmentTreeNode buildTree(int start, int end) {
if(start > end) {
return null;
}
SegmentTreeNode root = new SegmentTreeNode(start, end);
if(start == end) {
return root;
}
int mid = start + (end - start) / 2;
root.left = buildTree(start, mid);
root.right = buildTree(mid + 1, end);
return root;
}
private int querySum(SegmentTreeNode root, int start, int end) {
if(root.start == start && root.end == end) {
return root.sum;
}
int mid = root.start + (root.end - root.start) / 2;
int leftsum = 0, rightsum = 0;
if(start <= mid) {
leftsum = querySum(root.left, start, Math.min(mid, end));
}
if(end >= mid + 1) {
rightsum = querySum(root.right, Math.max(start, mid + 1), end);
}
return leftsum + rightsum;
}
private void add(SegmentTreeNode root, int index, int value) {
if(root.start == root.end && root.end == index) {
root.sum += value;
return;
}
int mid = root.start + (root.end - root.start) / 2;
if(index <= mid) {
add(root.left, index, value);
} else {
add(root.right, index, value);
}
root.sum = root.left.sum + root.right.sum;
}
public int querySum(int start, int end) {
return querySum(root, start, end);
}
public void add(int index, int value) {
add(root, index, value);
}
}
}