JAVA程序设计:计算右侧小于当前元素的个数(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 个更小的元素.

思路:我们先看另一道题:

给你一个数组,对于每个位置i,求出所有在i之前的比位置i上的数大的数

这不就是求逆序数嘛,这道题不是大同小异嘛,我们想一下求逆序数比较快速的方法,树状数组? 归并排序?线段树?

其实都是可以的,我们采用比较常用的归并排序吧。

对于三个数组的解释:

temp:存储元素的初始索引

indexes:存储元素排序后的最终索引

counter:每个位置上的答案

class Solution {
	private int[] temp;
	private int[] counter;
	private int[] indexes;
    public List<Integer> countSmaller(int[] nums) {
    	List<Integer> res=new ArrayList<>();
    	int len=nums.length;
    	if(len==0) return res;
    	
    	temp=new int[len];
    	counter=new int[len];
    	indexes=new int[len];
    	
    	for(int i=0;i<len;i++) indexes[i]=i;
    	
    	mergeAndCountSmaller(nums,0,len-1);
    	
    	for(int i=0;i<len;i++)
    		res.add(counter[i]);
    	
    	return res;
    }
    
    private void mergeAndCountSmaller(int[] nums,int l,int r)
    {
    	if(l==r) return;
    	
    	int mid=l+(r-l)/2;
    	mergeAndCountSmaller(nums,l,mid);
    	mergeAndCountSmaller(nums,mid+1,r);
    	
    	if(nums[indexes[mid]]>nums[indexes[mid+1]])
    		mergeOfTwoSortedArrAndCountSmaller(nums,l,mid,r);
    }
    
    private void mergeOfTwoSortedArrAndCountSmaller(int[] nums,int l,int mid,int r)
    {
    	for(int i=l;i<=r;i++)
    		temp[i]=indexes[i];
    	int i=l,j=mid+1;
    	for(int k=l;k<=r;k++)
    	{
    		if(i>mid)
    		{
    			indexes[k]=temp[j];
    			j++;
    		}
    		else if(j>r)
    		{
    			indexes[k]=temp[i];
    			i++;
    			counter[indexes[k]]+=r-mid;
    		}
    		else if(nums[temp[i]]<=nums[temp[j]])
    		{
    			indexes[k]=temp[i];
    			i++;
    			counter[indexes[k]]+=(j-mid-1);
    		}
    		else
    		{
    			indexes[k]=temp[j];
    			j++;
    		}
    	}
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值