LeetCode每日一题(Count of Smaller Numbers After Self)

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].

Example 1:

Input: nums = [5,2,6,1]
Output: [2,1,1,0]
Explanation:
To the right of 5 there are 2 smaller elements (2 and 1).
To the right of 2 there is only 1 smaller element (1).
To the right of 6 there is 1 smaller element (1).
To the right of 1 there is 0 smaller element.

Example 2:

Input: nums = [-1]
Output: [0]

Example 3:

Input: nums = [-1,-1]
Output: [0,0]

Constraints:

  • 1 <= nums.length <= 105
  • -104 <= nums[i] <= 104

思路:

开始看到这题基本没有头绪,想过用binary heap或者btree map来解决但是都失败了,看了一下别人的答案,才发现这原来就是一个merge sort的题。

merge sort大家应该都比较熟悉, 此题其实就是在merge阶段增加了一个计数的过程, 此时我们得到了两个有序的数组left和right, 依次成对的对比两个数组里的元素,挑小的放到合并数组里,这时候如果left里的元素比较小,那证明所有前面放进去的right里的元素都符合我们的条件(在left[i]的右侧,并且比left[i]要小)。

代码(Rust):

impl Solution {
    fn sort(mut nums: Vec<(usize, i32)>, counts: &mut Vec) -> Vec<(usize, i32)> {
        match nums.len() {
            1 => return nums,
            2 => {
                if nums[0].1 > nums[1].1 {
                    counts[nums[0].0] += 1;
                    nums.swap(0, 1);
                }
                return nums;
            }
            _ => {
                let (left, right) = nums.split_at(nums.len() / 2);
                let (mut left, mut right) = (left.to_vec(), right.to_vec());
                left = Solution::sort(left, counts);
                right = Solution::sort(right, counts);
                let (mut i, mut j) = (0, 0);
                let mut l = Vec::new();
                let mut right_count = 0;
                while i < left.len() && j < right.len() {
                    if left[i].1 <= right[j].1 {
                        counts[left[i].0] += right_count;
                        l.push(left[i]);
                        i += 1;
                    } else {
                        right_count += 1;
                        l.push(right[j]);
                        j += 1;
                    }
                }
                while i < left.len() {
                    counts[left[i].0] += right_count;
                    l.push(left[i]);
                    i += 1;
                }
                while j < right.len() {
                    l.push(right[j]);
                    j += 1;
                }
                return l;
            }
        }
    }
    pub fn count_smaller(nums: Vec) -> Vec {
        let len = nums.len();
        let l: Vec<(usize, i32)> = nums.into_iter().enumerate().collect();
        let mut counts = vec![0; len];
        Solution::sort(l, &mut counts);
        counts
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值