当前位置:   article > 正文

LeetCode 315. 计算右侧小于当前元素的个数_给你一个整数数组 nums ,按要求返回一个新数组 counts 。数组 counts 有该性

给你一个整数数组 nums ,按要求返回一个新数组 counts 。数组 counts 有该性

题目

给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。
链接:https://leetcode-cn.com/problems/count-of-smaller-numbers-after-self

示例

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

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

思路

1.暴力法

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var countSmaller = function(nums) {
    let len = nums.length;
    let res = new Array(len).fill(0);
    for(let i = len -1; i>=0;--i){
        for(let j = i+1; j<len;++j){
            if(nums[i]>nums[j]){
                res[i]++;
            }
        }
    }
    return res;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

从最后一个元素开始遍历,比较他和后面元素的大小,并记录,但这个会超时,不能ac

2. 遍历后的数组排序

因为每个元素的遍历都要,和之后的所有元素进行比较,那如果对后面的元素进行排序,当遇到比该元素小的值时,停止比较,记录一下之后元素的个数。代码如下

/**
 * @param {number[]} nums
 * @return {number[]}
 */
function ListNode(value){
    this.val = value;
    this.next = null
    this.length = 1;
}

var countSmaller = function(nums) {
    let len = nums.length;
    let head = new ListNode(-1);
    let res = new Array(len).fill(0);
    for(let i = len -1; i>=0;--i){
        let pre = head;
        while(pre.next && pre.next.val>=nums[i]){
            pre.next.length++;
            pre = pre.next;
        }
        let node = new ListNode(nums[i]);
        node.length = pre.next?pre.next.length+1:0;
        node.next = pre.next;
        pre.next = node;
        res[i] = node.length;
    }
    return res;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28

这个结果是可以ac的,但时间效率不高,本质还是O(n^2)。
在这里插入图片描述

3. 归并

其实这道题和另一道求逆序对个数的题很像,但那道题是求逆序对的总数,而这道题是求每个位置开始的逆序对,一开始也是想用归并做的,但考虑到归并的时候会是数组的索引会变,如果要新增了一个索引数组作为映射,貌似也很麻烦,所以就没往归并的方向做下去了。 但看题解的时候,发现可以归并一个索引数组,代码如下:

/**
 * @param {number[]} nums
 * @return {number[]}
 */
var countSmaller = function(nums) {
    let len = nums.length;
    let arr_index = new Array(len);
    nums.forEach((_,key)=>{
        arr_index[key] = key;
    })
    let ans = new Array(len).fill(0);
    const merge = (left, right)=>{
        let llen = left.length;
        let rlen = right.length;
        let len = llen+rlen;
        let res = new Array(len);
        for(let i = 0, j= 0, k= 0 ; k <len;++k){
            if(i == llen){
                res[k] = right[j++]
            }else if(j == rlen){
                res[k] = left[i++];
            }else if(nums[left[i]]>nums[right[j]]){
                ans[left[i]]+=(rlen-j);
                res[k] = left[i++];
            }else{
                res[k] = right[j++];
            }
        }
        return res;
    }

    const mergeSort = (arr)=>{
        if(arr.length<2){
            return arr;
        }
        let len = arr.length;
        let mid = len>>1;
        let left = arr.slice(0,mid);
        let right = arr.slice(mid);
        return merge(mergeSort(left), mergeSort(right));
    }
    mergeSort(arr_index);
    return ans;
};
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小丑西瓜9/article/detail/87122
推荐阅读
相关标签
  

闽ICP备14008679号