Merge sort and its extension

Merge sort

  • Before learning merge sort, let's consider how to find the maximum value of an array?
    Our first thought is to traverse the array, compare the size and record the maximum value, but what if we want to use recursive implementation? We can divide the array into two parts of equal length, find the maximum values on both sides, finally take the maximum value, and further divide the two parts (recursively) until only one value of the array is returned.
public class GetMax {
	//Recursive maximum
	//An array is divided into two parts and solved recursively
	//Find the maximum value on the left and the maximum value on the left, and finally take a maximum value
	public static void main(String[] args) {
		int arr[] = {1,3,5,2,3,7,4};
		System.out.println(getMax(arr));
	}
	public static int getMax(int[] arr) {
		return process(arr, 0, arr.length-1);
	}
	public static int process(int[] arr,int L,int R) { 
		//arr is the array that needs to find the maximum value, L is the start position of the array, and R is the end position of the array
		if(L==R) {
			//Recursion end condition, to L==R, so that only one value in the split array is of course the maximum value
			return arr[L];
		}
		//The middle position of the mid array, that is, (R+L)/2. In order to prevent R+L from exceeding the range (int has a range), the starting position plus half is also the middle value
		// >>Shift right operator > > n is equivalent to dividing by 2 to the nth power < < shift left operator < < n is equivalent to multiplying by 2 to the nth power
		int mid = L + ( (R-L)>>1 );
		int rightMax = process(arr, L, mid);//Recursively find the left maximum
		int leftMax = process(arr, mid+1, R);//Recursively find the maximum value on the right
		return Math.max(rightMax,leftMax); //Returns the maximum left and right values
	}
}

Here, we can use this idea to divide an array into two arrays. If the two arrays have been sorted, we just need to merge the two arrays from small to large into a new array, and finally save the merged array to the array to be sorted.


The ugly painting, the author is at this level, don't spray if you don't like it!!!

package Sort;

public class MergeSort {
	//Merge sort
	public static void main(String[] args) {
		int [] arr = {1,5,3,2,7,4};
		mergeSort(arr);
		for(int i=0;i<arr.length;i++) {
			System.out.print(arr[i]+" ");
		}
	}
	public static void mergeSort(int[] arr) {
		if(arr==null||arr.length<1) {
			//If the array is empty, sorting cannot be performed. If the length of arr is only one, sorting is not required
			return ;
		}
		process(arr,0,arr.length-1);
	}
	public static void process(int[] arr,int L,int R) {
		if(L==R) {
			//L==R there is only one element in the split array that does not need to be sorted
			return;
		}
		//Intermediate value 
		int mid = L + ((R-L)>>1);
		process(arr, L, mid);//Split the array and sort the left array
		process(arr, mid+1, R);//Split the array and sort the right array
		merge(arr,L,mid,R);//The left array and the right array have been merged
	}
	private static void merge(int[] arr, int L, int mid, int R) {
		//Create an auxiliary array, merge the arrays on both sides into the help auxiliary array, and save it into the arr array
		int help[] = new int[R-L+1];
		int p1=L;//Left array pointer, that is, the left corner mark
		int p2=mid+1;//Right array knitting, i.e. right corner mark
		int i=0;//Auxiliary array angle
		while(p1<=mid&&p2<=R) {
			help[i++] = arr[p1]<=arr[p2]?arr[p1++]:arr[p2++];
			//If the condition before the ternary operator is true, the statement before the colon will be executed, otherwise the statement after the colon will be executed
		}
		while(p1<=mid) {
			help[i++] = arr[p1++];
		}
		while(p2<=R) {
			help[i++] = arr[p2++];
		}
		//Only one of these two while files will be executed at most, because one condition in the first while is not tenable
		for(i =0;i<help.length;i++) {
			arr[L+i] = help[i];
		}
	}
}

Note: the time complexity of merge sorting is O(N*logN) and the space complexity is O(N)
The reason is to search other authors. The author is lazy and the author doesn't understand it

Extended Topic:
    Small sum: in an array, the numbers on the left of each number that are smaller than the current number are accumulated, which is called the small sum of the array. Find the small sum

    When we see this problem, the first thing we want is to solve it violently, and the two-tier for loop is completed directly (well, I think so), but the time complexity of this method is O(N^2). We can solve this problem by merging and sorting, and the time complexity of this method is only O(NlogN).
    We must first change our thinking and find that the left side of each number is smaller than the current number, that is, the sum of the right side is larger than this number

With this idea, we only need to count the number (R-p2+1) larger than this number (arr[p1]) if the number on the left is less than the number on the right during merging. If the number on the left is greater than the number on the right, we don't need to change it, because this number has been calculated before merging, so it won't be repeated (the author doesn't know what to say here / bald head. Anyway, just look at the code)

	package Sort;

public class smallSum {
	//Seek small sum
//	static int res=0; you can save the results so that you don't have to set the return value
	public static void main(String[] args) {
		int[] arr = {1,3,5,2,4};
		int res=getSmallSum(arr);//Record results
		System.out.println(res);
	}
	public static int getSmallSum(int[] arr) {
		if(arr==null||arr.length<1) return 0; //When the array does not exist or the length is one, the small sum is 0
		return process(arr, 0, arr.length-1);
	}
	public static int process(int[] arr,int L,int R) {
		if(L==R) {
			return 0;
		}
		int mid = L+((R-L)>>1);
		return 
		+process(arr, L, mid)
		+process(arr, mid+1, R)
		+merge(arr,L,mid,R);
	}
	private static int merge(int[] arr, int L, int mid, int R) {
		int[] help = new int[R-L+1];
		int res=0;//Record the small sum of the divided array
		int p1=L,p2=mid+1,i=0;//See mergeSort
		while(p1<=mid&&p2<=R) {
			res+= arr[p1]<arr[p2]? (R-p2+1) * arr[p1] :0;
			//Because the array on the right is ordered, the numbers after P2 are larger than p1, so you can directly multiply R-p2+1 by arr[p1]
			help[i++] = arr[p1]<=arr[p2]?arr[p1++]:arr[p2++];//sort
		}
		//Two while processes are saved with out of bounds but
		while(p1<=mid) {
			help[i++] = arr[p1++];
		}
		while(p2<=R) {
			help[i++] = arr[p2++];
		}
		//Save the sorted results to the array to be sorted
		for(i =0;i<help.length;i++) {
			arr[L+i]=help[i];
		}
		return res;
	}
}

Finally, let me tell you that the author is also Xiaobai. This article only records his ideas. There may be many places that are wrong or incorrect understanding. Don't spray if you don't like it!! don't spray if you don't like it
Finally, the address explained by Zuo Shen is attached Zuo Shen explains the algorithm of station B Zuo Shen spoke very clearly. You can take a look

Tags: Algorithm Permutation

Posted on Fri, 26 Nov 2021 19:52:16 -0500 by phpcodec