[LeetCode]--315. Count of Smaller Numbers After Self(Binary Search Tree && Merge Sort)

Problem

Problem_Link
这里写图片描述

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];
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值