Small sum questions and questions in reverse order (merge and sort, interview must be taken every year)

Extension of merge sort

Small sum problem and reverse order pair problem

Small and problems

In an array, the numbers on the left of each number that are smaller than the current number are added up, which is called the small sum of the array. Find the small sum of an array.

Problem conversion

*The original problem is to find a number whose left is smaller than it, and then add it all
*For example: example: [1,3,4,2,5] a number smaller than 1 on the left of 1, no; 3 the number smaller than 3 on the left, 1; 4 numbers smaller than 4 on the left, 1 and 3; 2 the number smaller than 2 on the left, 1; 5 numbers smaller than 5 on the left, 1, 3, 4, 2; Therefore, the small sum is 1 + 1 + 3 + 1 + 1 + 3 + 4 + 2 = 16
*We can think in reverse, we can determine an element, find how many numbers are larger on the right, and then multiply the number by this number, which is also equal to the minimum sum, but here is to find the minimum of this number in advance.
*[1,3,4,2,5], the number larger than 1 on the right of 1 is 3, 4, 2 and 5, so 41. Then there are two numbers on the right of 3: 4 and 5, which are larger than 3, a total of two numbers. So 32 = 6. For 4, there are: 5, and one number is greater than five, so: 4 * 1 = 4. Similarly, there are: 2. Total: 4 + 6 + 4 + 2 = 16.

How to realize small sum by merging

We think that merging the two ordered parts is to compare the size separately and put them into the auxiliary space. We can use the merged comparison to put them into the auxiliary space. How many larger numbers are found in the latter part than in the previous part. Then multiply the quantity by the number to calculate the minimum sum containing the number.

Why is there no repetition, over calculation and missing calculation

First of all, I use concise language to describe: when the two parts are merged, we only calculate the minimum sum of the latter part to the former part because the former part has been calculated. Why not? Because the first part can also be divided into half, and the other half has also experienced a merger. Before repeatedly dividing, only one number will be drawn in the end. From this figure, we can know that there will be no repetition and over calculation.



Let's look at these numbers and suppose we have abcdefghij these numbers. For c, before merging with c, ab has gone through a merger. The minimum sum of them has been calculated. When merging with c, abc has calculated the minimum sum. Then abc merges with de. for c, ab has calculated with it, and then he calculates with De. Similarly, the merger of abcd and fghij is the same.

Changes and comparison of three functions

At the beginning of the function call, the return value has a certain int, not void, in order to return the minimum sum

	public static int smallsum(int [] arr) {
		
		if(arr == null || arr.length < 2) {
			return 0;
		}
		return mergesort(arr,0,arr.length-1);
	}
	

The latter main recursive function does not directly call two functions, but directly adds the return value of two recursive processes and merging processes. Logically, it is: the minimum sum of the left undivided part plus the minimum sum of the right part plus the minimum sum of the two parts combined

public static  int mergesort(int [] arr, int l,int r) {
		if(l==r) {
			return 0;
		}
		int mid;
		mid = l + ((r-l)>>1);
		return mergesort(arr,l,mid)+mergesort(arr,mid+1,r)+merge(arr,l,mid,r);
	}

The function of how to merge processes has a return value, and finally the return value appears obviously. Then, the minimum value operation is added in the while process of the first merge:
res+=arr[p1]<arr[p2]?(r-p2+1)*arr[p1]:0;

 public static int merge(int []arr,int l,int m ,int r) {
    	int [] help = new int [r-l+1];
    	int i=0;
    	int p1=l;
    	int p2=m+1;
    	int res=0;
    	while(p1<=m&&p2<=r) {
    		res += arr[p1]<arr[p2]?(r-p2+1)*arr[p1]:0;
    		help[i++]=arr[p1]<arr[p2]?arr[p1++]:arr[p2++];
    	}
    	while(p1<=m) {
    		help[i++]=arr[p1++];
    	}
    	while(p2<=r) {
    		help[i++]=arr[p2++];
    	}
    	for(i = 0;i<help.length;i++) {
    		arr[i+l]=help[i];
    	}
    	return res;
    }

My code

public class Smallsum {
	
	public static int smallsum(int [] arr) {
		
		if(arr == null || arr.length < 2) {
			return 0;
		}
		return mergesort(arr,0,arr.length-1);
	}
	
	public static  int mergesort(int [] arr, int l,int r) {
		if(l==r) {
			return 0;
		}
		int mid;
		mid = l + ((r-l)>>1);
		return mergesort(arr,l,mid)+mergesort(arr,mid+1,r)+merge(arr,l,mid,r);
	}
    public static int merge(int []arr,int l,int m ,int r) {
    	int [] help = new int [r-l+1];
    	int i=0;
    	int p1=l;
    	int p2=m+1;
    	int res=0;
    	while(p1<=m&&p2<=r) {
    		res += arr[p1]<arr[p2]?(r-p2+1)*arr[p1]:0;
    		help[i++]=arr[p1]<arr[p2]?arr[p1++]:arr[p2++];
    	}
    	while(p1<=m) {
    		help[i++]=arr[p1++];
    	}
    	while(p2<=r) {
    		help[i++]=arr[p2++];
    	}
    	for(i = 0;i<help.length;i++) {
    		arr[i+l]=help[i];
    	}
    	return res;
    }
    
    
    public static void main(String[] args) {
    	int[] arr;
    	arr = new int[]{1,1,1,4};
    	int r=smallsum(arr);
    	System.out.println(r);
    	return ;
    }
}

Code accident scene

No matter how I started compiling, it was stack overflow, stack overflow. I can't figure it out. My recursion doesn't have infinite calls, and then I found that the problem actually appeared in;
int mid = l + (r-l)>>1; In fact, this expression is the last displacement, not the addition after the displacement.
Finally, a bracket int mid = L + ((R - L) > > 1) will be added;

Inverse pair problem

In an array, if the number on the left is larger than the number on the right, it will be folded into two numbers to form an inverse pair. Please print all inverse pairs.

My thoughts

First, merge and sort, and then in the process of merging, like the minimum sum, find all the numbers on the right that are smaller than on the left. Then, you should promise to traverse it. If you don't print but just find the quantity, you can directly:
r-p2 gets the number

#Summary for all similar, find the relationship between the front and the back two elements of an array (part), and consider the change of merging and sorting, recursive method. Solve. Note that the application of the ordered properties of the two parts, such as the minimum sum and finding the number, directly r-p2+1, obtains the number of all numbers greater than arr[p1], only because the ordered parts greater than P2 are greater than arr [P2]. It should also be noted that it is necessary to keep sorting and put numbers into the auxiliary space, so that one element will not be calculated repeatedly in a merge.

Tags: Algorithm Interview

Posted on Wed, 10 Nov 2021 18:02:19 -0500 by phpform08