Leetcode:315. 计算右侧小于当前元素的个数

Leetcode:315. 计算右侧小于当前元素的个数

题目描述

给定一个整数数组 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 个更小的元素.

思路

思路1 暴力遍历比较

直接对每个位置的数和之后的数比较

思路2 归并排序+索引数组

代码

代码1

class Solution {
    public List countSmaller(int[] nums) {
        ArrayList result = new ArrayList<>();
        for(int i = 0; i < nums.length; i++){
            int count = 0;
            for(int j = i + 1; j < nums.length; j++){
                if (nums[i] > nums[j]){
                    count += 1;
                }
            }
            result.add(count);
        }
        return result;
    }
}

代码2

class Solution {
    private int[] indexs;
    private int[] counters;
    private int[] temp;
    
    public List countSmaller(int[] nums) {
        ArrayList result = new ArrayList<>();
        indexs = new int[nums.length];
        counters = new int[nums.length];
        temp = new int[nums.length];
        for(int i = 0; i < nums.length; i++){
            indexs[i] = i;
            counters[i] = 0;
        }
        mergeSort(nums, 0, nums.length - 1);
        for(int i = 0; i < counters.length; i++){
            result.add(counters[i]);
        }
        return result;
    }
    
    
    private void mergeSort(int[] nums, int left, int right){
        if (left < right){
            int mid = (left + right) / 2;
            mergeSort(nums, left, mid);
            mergeSort(nums, mid + 1, right);
            mergeHelper(nums, left, mid, right);
        }
    }
    
    private void mergeHelper(int[] nums, int left, int mid , int right){
        int tempIndex = left;
        int leftIndex = left;
        int rightIndex = mid + 1;
        while (leftIndex <= mid && rightIndex <= right){
            if (nums[indexs[leftIndex]] <= nums[indexs[rightIndex]]){
                temp[tempIndex] = indexs[leftIndex];
                counters[indexs[leftIndex]] += rightIndex - mid - 1;
                leftIndex++;
            }else{
                temp[tempIndex] = indexs[rightIndex];
                rightIndex++;
            }
            tempIndex++;
        }
        while(leftIndex <= mid){
            temp[tempIndex] = indexs[leftIndex];
            counters[indexs[leftIndex]] += rightIndex - mid - 1;
            leftIndex++;
            tempIndex++;
        }
        while(rightIndex <= right){
            temp[tempIndex] = indexs[rightIndex];
            rightIndex++;
            tempIndex++;
        }
        for(int i = left; i <= right; i++){
            indexs[i] = temp[i];
        }
    }
}

复杂度分析

思路1时间复杂度

$O(n^2)$

思路1空间复杂度

$O(n)$

思路2时间复杂度

$O(nlog(n))$

思路2空间复杂度

$O(n)$


文章作者: 小风雷
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 小风雷 !
评论
 上一篇
Leetcode:395. 至少有K个重复字符的最长子串 Leetcode:395. 至少有K个重复字符的最长子串
Leetcode:395. 至少有K个重复字符的最长子串题目描述找到给定字符串(由小写字符组成)中的最长子串 T , 要求 T 中的每一字符出现次数都不少于 k 。输出 T 的长度。 示例 1:输入: s = "aaabb&qu
2020-04-21
下一篇 
Leetcode:218. 天际线问题 Leetcode:218. 天际线问题
Leetcode: 218. 天际线问题题目描述城市的天际线是从远处观看该城市中所有建筑物形成的轮廓的外部轮廓。现在,假设您获得了城市风光照片(图A)上显示的所有建筑物的位置和高度,请编写一个程序以输出由这些建筑物形成的天际线(图B)。
2020-04-19
  目录