Problem
Solutions
Binary Search Tree
So, see the code!
public class Solution {
class Node {
Node left, right;
int val, sum, dup = 1;
// "val" means the value of this node, "sum" represents the total number ofon its left bottom side.
public Node(int v, int s) {
val = v;
sum = s;
}
}
public List<Integer> countSmaller(int[] nums) {
Integer[] ans = new Integer[nums.length];
Node root = null;
for (int i = nums.length; i >= 0; i--) {
root = insert(nums[i], root, ans, i, 0);
}
return Arrays.asList(ans);
}
private Node insert(int num, Node node, Integer[] ans, int i, int preSum) {
if (node == null) {
node = new Node(num, 0);
} else if (node.val == num) {
node.dup++;
ans[i] = preSum + node.sum;
} else if (node.val > sum) {
node.sum++;
// preSum--attention
node.left = insert(num, num.left, ans, i, preSum);
} else {
// preSum + node.dup + node.sum
node.right = insert(num, num.right, ans, i, preSum + node.dup + node.sum);
}
return node;
}
}
Merge Sort Solution(Python)
Reference:https://discuss.leetcode.com/topic/31162/mergesort-solution
The smaller numbers on the right of a number are exactly those that jump from its right to its left during a stable sort. So I do mergesort with added tracking of those right-to-left jumps.
At first, I want to understand the Python Solution use the merge sort solution!
def countSmaller(self, nums):
def sort(enum):
half = len(enum) / 2
if half:
left, right = sort(enum[:half]), sort(enum[half:])
for i in range(len(enum))[::-1]:
if not right or left and left[-1][1] > right[-1][1]:
smaller[left[-1][0]] += len(right)
enum[i] = left.pop()
else:
enum[i] = right.pop()
return enum
smaller = [0] * len(nums)
sort(list(enumerate(nums)))
return smaller
Merge Sort Solution(Java)
Reference: https://discuss.leetcode.com/topic/31554/11ms-java-solution-using-merge-sort-with-explanation
The Merge Sort idea is follows!
Variables We Need
1. left[]
and right[]
, do the merge sort operation, supposed that left[]
and right[]
are already sorted.
2. rightcount is used to [record how many numbers from right[]
.
3. count[left.length]: Because the right[]
doesn’t need count to record this.
Variables We Do
1. Increase the rightcount by 1 when u move a number from right[]
into the new sorted array.
2. Increase the count[index of number from the left[]] by the present value of rightcount when u move a number from left[index]
into the new sorted array.
int[] count;
public List<Integer> countSmaller(int[] nums) {
List<Integer> res = new ArrayList<Integer>();
count = new int[nums.length];
int[] indexes = new int[nums.length];
for(int i = 0; i < nums.length; i++){
indexes[i] = i;
}
mergesort(nums, indexes, 0, nums.length - 1);
for(int i = 0; i < count.length; i++){
res.add(count[i]);
}
return res;
}
private void mergesort(int[] nums, int[] indexes, int start, int end){
if(end <= start){
return;
}
int mid = (start + end) / 2;
mergesort(nums, indexes, start, mid);
mergesort(nums, indexes, mid + 1, end);
merge(nums, indexes, start, end);
}
private void merge(int[] nums, int[] indexes, int start, int end){
int mid = (start + end) / 2;
int left_index = start;
int right_index = mid+1;
int rightcount = 0;
int[] new_indexes = new int[end - start + 1];
int sort_index = 0;
while(left_index <= mid && right_index <= end){
if(nums[indexes[right_index]] < nums[indexes[left_index]]){
new_indexes[sort_index] = indexes[right_index];
rightcount++;
right_index++;
}else{
new_indexes[sort_index] = indexes[left_index];
count[indexes[left_index]] += rightcount;
left_index++;
}
sort_index++;
}
while(left_index <= mid){
new_indexes[sort_index] = indexes[left_index];
count[indexes[left_index]] += rightcount;
left_index++;
sort_index++;
}
while(right_index <= end){
new_indexes[sort_index++] = indexes[right_index++];
}
for(int i = start; i <= end; i++){
indexes[i] = new_indexes[i - start];
}
}