/** * 给定一个数组 nums ,如果 i < j 且 nums[i] > 2*nums[j] 我们就将 (i, j) 称作一个重要翻转对。 你需要返回给定数组中的重要翻转对的数量。 */ /*** * 没特别明白 思路:1.原始数组分割子数组,分治求解 solve(A)=solve(A1)+solve(A2)+cross(A1,A2),无限套娃直到子数组无法分割返回0 2. 对于每个数组内,计算左边一半和右边一半比较的结果,因为1是基础,基础之后按照归并排序合并成2,所以后面的比较两边每一半都是有序的,所以如果nums[i]>2*nums[j], 那么从i到mid的每个都大于j,减少计算 3. 统计之后继续合并,下次对于4而言左右边的2都是有序的 */ public class reversepair { public static void main(String[] args) { int []nums={2,4,3,5,1}; System.out.println(reversePairs(nums)); } //暴力超时 public static int reversePairs1(int[] nums) { int []count=new int[nums.length]; for(int j=1;j<nums.length;j++){ for(int i=0;i<j;i++){ if(nums[i]-nums[j]>nums[j]){ count[j]++; } } } int num=0; for(int i=0;i<count.length;i++){ num=num+count[i]; } return num; } //归并排序 public static int reversePairs(int[] nums) { if(nums.length<2){ return 0; } return helper(nums,0,nums.length-1); } public static int helper(int[] nums,int left,int right) { if(left==right){ return 0; }else{ int mid=(left+right)/2; int n1=helper(nums,left,mid); int n2=helper(nums,mid+1,right); int ret=n1+n2; //统计下标对数量 这里数组是归并排序结束的,递增的 int i=left; int j=mid+1; while(i<=mid){ while((j<=right)&&((long) nums[i] > 2 * (long) nums[j])){ j++; } ret=ret+j-mid-1; i++; } //合并两个排序数组(对数组进行排序) int []sorted=new int[right-left+1]; int p1=left; int p2=mid+1; int p=0; while(p1<=mid||p2<=right){ if(p1>mid){ sorted[p++]=nums[p2++]; }else if(p2>right){ sorted[p++]=nums[p1++]; }else{ if(nums[p1]<nums[p2]){ sorted[p++]=nums[p1++]; }else{ sorted[p++]=nums[p2++]; } } } for(int k=0;k<sorted.length;k++){ nums[left+k]=sorted[k]; } return ret; } } }