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
}
}