面试题51. 数组中的逆序对_315. 计算右侧小于当前元素的个数

45 篇文章 0 订阅
16 篇文章 0 订阅

问题

在这里插入图片描述

例子

在这里插入图片描述

思路
暴力方法,两个for循环,超时

  • 方法1
    $$

    $$

    使用对并排序,两个数组排好序归并时【左边数组 l=i; l<=m,右边数组r=m+1; r<=j】:如果nums[l]>nums[r],由于都已经排好序,则l到m都>nums[r],有m-r+1个

  • 方法2
    $$

    $$

代码

//方法1
class Solution {
    private int res=0;
    public int reversePairs(int[] nums) {
        sort(nums,0,nums.length-1,new int[nums.length]);
        
        return res;
    }

    public void sort(int[] nums,int i, int j,int[] temp) {
        if(i<j) {
            int m = i+(j-i)/2;
            sort(nums,i,m,temp);
            sort(nums,m+1,j,temp);
           
	        merge(nums,i,m,j,temp);
	        
        }
    }
    
    public void merge(int[] nums,int i, int m, int j,int[] temp) {
        int ii = i;
        int l=i,r=m+1;
        while(l<=m && r<=j) {
            if(nums[l]<=nums[r]) {
                temp[i++]=nums[l++];
                
            }else{
                // 则从 nums[l] 到 nums[m] 必定都是大于 nums[r] 的,
                // 因为两部分的子数组已经是各自有序的
                res += m-l+1;
                
                temp[i++]=nums[r++];
                
            }
        }
        for(; l<=m; l++)
            temp[i++]=nums[l];
        for(; r<=j; r++)
            temp[i++]=nums[r];
        System.arraycopy(temp,ii,nums,ii,j-ii+1);
       
        
        
    }
}

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

思路
归并
因为要记录每个下标后面有几个数字小于该数,所以使用二维数组记录每个数字的下标,排序的时候,带着该元素所在的下标一起排序

使用int数组记录结果

  • 方法1
    归并时,两个有序数组,arr1,arr2,如果arr1[l]>arr2[r],则arr1中下标在l之后的元素都>arr2[r]
  • 方法2
    归并时,两个有序数组,arr1,arr2, 如果arr[l]<=arr[r],则arr[l]>所有的arr2中下标<r的数
//方法1
class Solution {
    int[] res = null;
    public List<Integer> countSmaller(int[] nums) {
        if(nums.length==0) return new ArrayList<Integer>();
        res = new int[nums.length];
        int[][] temp = new int[nums.length][2];
        int[][] arr = new int[nums.length][2];
        for(int i=0; i<nums.length; i++) {
        	arr[i][0]=nums[i];
        	arr[i][1]=i;
        }
     
        sort(0,nums.length-1,arr,temp);
        List<Integer> list = new ArrayList<>();
        for(int n:res){
            list.add(n);
        }
        return list;
        
    }
    
    public void sort(int i, int j, int[][] arr, int[][] temp) {
        if(i<j) {
            int m = i+(j-i)/2;
            sort(i,m,arr,temp);
            sort(m+1,j,arr,temp);
            merge(i,m,j,arr,temp);
        }
    }
    
    public void merge(int i,int m,int j,int[][] arr,int[][] temp) {
        int l=i,r=m+1,ii=i;
        
        while(l<=m && r<=j) {
            if(arr[l][0]<=arr[r][0]){
                // res[arr[l][1]]+=(r-1)-(m+1)+1;
                temp[i++]=arr[l++];
                
            }else{
                for(int k=l; k<=m; k++)
                {
                    int index = arr[k][1];
                    res[index]++;    
                }
                

                temp[i++]=arr[r++];
                    
            }
        }
        for(;l<=m;l++) 
        {
            // res[arr[l][1]]+=j-(m+1)+1;
            temp[i++]=arr[l];
        }
     
        for(;r<=j;r++) 
            temp[i++]=arr[r];
        
        System.arraycopy(temp, ii, arr, ii, j-ii+1);
    }
    
    
}
//方法2
class Solution {
    int[] res = null;
    public List<Integer> countSmaller(int[] nums) {
        if(nums.length==0) return new ArrayList<Integer>();
        res = new int[nums.length];
        int[][] temp = new int[nums.length][2];
        int[][] arr = new int[nums.length][2];
        for(int i=0; i<nums.length; i++) {
        	arr[i][0]=nums[i];
        	arr[i][1]=i;
        }
     
        sort(0,nums.length-1,arr,temp);
        List<Integer> list = new ArrayList<>();
        for(int n:res){
            list.add(n);
        }
        return list;
        
    }
    
    public void sort(int i, int j, int[][] arr, int[][] temp) {
        if(i<j) {
            int m = i+(j-i)/2;
            sort(i,m,arr,temp);
            sort(m+1,j,arr,temp);
            merge(i,m,j,arr,temp);
        }
    }
    
    public void merge(int i,int m,int j,int[][] arr,int[][] temp) {
        int l=i,r=m+1,ii=i;
        
        while(l<=m && r<=j) {
            if(arr[l][0]<=arr[r][0]){
                res[arr[l][1]]+=(r-1)-(m+1)+1;
                temp[i++]=arr[l++];
                
            }else{
                // for(int k=l; k<=m; k++)
                // {
                //     int index = arr[k][1];
                //     res[index]++;    
                // }
                

                temp[i++]=arr[r++];
                    
            }
        }
        for(;l<=m;l++) 
        {
            res[arr[l][1]]+=j-(m+1)+1;
            temp[i++]=arr[l];
        }
     
        for(;r<=j;r++) 
            temp[i++]=arr[r];
        
        System.arraycopy(temp, ii, arr, ii, j-ii+1);
    }
    
    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值