面試題51. 數組中的逆序對_315. 計算右側小於當前元素的個數

問題

在這裏插入圖片描述

例子

在這裏插入圖片描述

思路
暴力方法,兩個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);
    }
    
    
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章