LeetCode(315):计算右侧小于当前元素的个数 Count of Smaller Numbers After Self(Java)

2019.9.24 #程序员笔试必备# LeetCode 从零单刷个人笔记整理(持续更新)

这道题想要非暴力做不太简单,可以有两种o(nlgn)的方法:

1.归并排序+索引数组

对索引数组进行归并。在归并过程中,当位于左数组的元素i出列时候,右数组已经出列的元素均比其小,在结果数组中累加这个元素个数即可。

2.二叉搜索树

构建一棵深度为n的二叉树,将数组元素从后往前依次插入,每一个小于当前元素i的右侧元素个数=插入过程经过的结点数+经过结点左子树的结点总数。

同理可以求左/右侧大于/小于当前元素的个数。


传送门:计算右侧小于当前元素的个数

You are given an integer array nums and you have to return a new counts array. The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i].

给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。

示例:

输入: [5,2,6,1]
输出: [2,1,1,0] 
解释:
5 的右侧有 2 个更小的元素 (2 和 1).
2 的右侧仅有 1 个更小的元素 (1).
6 的右侧有 1 个更小的元素 (1).
1 的右侧有 0 个更小的元素.


import java.util.*;

/**
 *
 * You are given an integer array nums and you have to return a new counts array.
 * The counts array has the property where counts[i] is the number of smaller elements to the right of nums[i].
 * 给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是  nums[i] 右侧小于 nums[i] 的元素的数量。
 *
 */

public class CountOfSmallerNumbersAfterSelf {
     
    //归并排序+索引数组(同理可以求左侧大于/小于当前元素的个数)
    public List<Integer> countSmaller(int[] nums) {
     
        int[] numsIdx = new int[nums.length];
        Integer[] result = new Integer[nums.length];
        for(int i = 0; i < numsIdx.length; i++){
     
            numsIdx[i] = i;
        }
        Solution(nums, 0, nums.length - 1, numsIdx, result);
        return Arrays.asList(result);
    }

    public void Solution(int[] nums, int begin, int end, int[] numsIdx, Integer[] list){
     
        if(begin >= end){
     
            return;
        }
        int mid = (begin + end) >> 1;
        Solution(nums, begin, mid, numsIdx, list);
        Solution(nums, mid + 1, end, numsIdx, list);

        int leftIdx = begin;
        int rightIdx = mid + 1;
        int[] result = new int[end - begin + 1];
        int resultIdx = 0;
        while(leftIdx <= mid && rightIdx <= end){
     
            //当位于左数组的元素i出列时候,右数组已经出列的元素均比其小,累加元素个数
            if(nums[numsIdx[leftIdx]] <= nums[numsIdx[rightIdx]]){
     
                int idx = numsIdx[leftIdx++];
                result[resultIdx++] = idx;
                list[idx] += rightIdx - (mid + 1);
            }else{
     
                result[resultIdx++] = numsIdx[rightIdx++];
            }
        }
        if(leftIdx > mid){
     
            System.arraycopy(numsIdx, rightIdx, result, resultIdx, end - rightIdx + 1);
        }else{
     
            //当位于左数组的元素i出列时候,右数组已经出列的元素均比其小,累加元素个数
            while(leftIdx <= mid){
     
                int idx = numsIdx[leftIdx++];
                result[resultIdx++] = idx;
                list[idx] += rightIdx - (mid + 1);
            }
        }
        System.arraycopy(result, 0, numsIdx, begin, end - begin + 1);
    }

    //二叉搜索树
    //构建一棵深度为n的二叉树,将数组元素从后往前依次插入,每一个小于当前元素i的右侧元素个数=插入过程经过的结点数+经过结点左子树的结点总数
    class Node{
     
        Node left, right;
        int val, leftNodeSums, sameNodeSums = 1;
        public Node(int v, int s){
     
            val = v;
            leftNodeSums = s;
        }
    }
    public List<Integer> countSmaller2(int[] nums){
     
        Integer[] result = new Integer[nums.length];
        Node root = null;
        for(int i = nums.length - 1; i >= 0; i--){
     
            root = insert(nums[i], root, result, i, 0);
        }
        return Arrays.asList(result);
    }

    public Node insert(int num, Node node, Integer[] res, int idx, int preSum){
     
        if(node == null){
     
            node = new Node(num, 0);
            res[idx] = preSum;
        }
        else if(num == node.val){
     
            node.sameNodeSums++;
            res[idx] = preSum + node.leftNodeSums;
        }
        else if(num < node.val){
     
            node.leftNodeSums++;
            node.left = insert(num, node.left, res, idx, preSum);
        }
        //当前元素num小于当前结点node时,递归插入右子树,并更新次数preSum(经过的结点数+结点左子树的结点总数)
        else{
     
            node.right = insert(num, node.right, res, idx, preSum + node.sameNodeSums + node.leftNodeSums);
        }
        return node;
    }
}




#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#

你可能感兴趣的:(JAVA,LeetCode,数据结构与算法,数据结构与算法,LeetCode,逆序对,归并,二叉搜索树)