Find the k-th largest number of two ordered arrays

Keywords: Java Algorithm leetcode Interview

Title: give two one-dimensional int arrays a and B. where: A is an ordered array with length m and elements in good order from small to large. B is an ordered array with length n and elements arranged from small to large. We hope to find the maximum k numbers from the A and B arrays. It is required to use as few comparisons as possible.

Solution:

1. Firstly, the concept of upper median (algorithm prototype) is introduced

When writing the function to judge the upper median, first ensure that the lengths of the two arrays are the same.

1.1 when the length of two arrays is even

        eg: arr1 = {a,b,c,d};     arr2 = {e,f,g,h}, find the fourth largest number

  1. When b==f, b and F are the upper median       
  2. When B < f   When,   abe is less than f, so the first three smallest numbers include ab; gh is greater than f, that is, gh is greater than abef, so gh is certainly not the fourth largest number, so the fourth largest number can only be generated in cd and ef, so recursively find the upper median in cdef.
  3. When b > F   Similarly, the fourth largest number can be obtained only in ab and gh   Generated in, so recursively find abgh   Upper median.

1.2 when both array lengths are odd

        eg: arr1 = {a,b,c,d,e};     arr2 = {f,g,h,i,j}, find the 5th largest number

  1. When c==h, c and H are the upper median
  2. When c < h, abc is less than h and fg is less than h, so hij must be the number after the fifth digit, so only consider whether abc and fg meet the requirements. However, the recursive solution cannot be performed at this time, because the lengths of the two arrays are not equal, so it is necessary to manually judge the relationship between c and g
    1. c==g: c, G are the upper median
    2. C < G: abc is three of the first four small numbers, so the fifth largest number can only be in de   And fg, so recursively find the upper median in defg.
    3. c > G: abfg is less than c, and c is the upper median
  3. When C > H: the solution is the same as 2

2. Problem solving

There are different ways to solve the k parameter in the k-th largest number. Suppose that the length of array A is 10 and the length of array B is 15

eg: Note: the number in the array only represents the position, not the value

arr1 = {1,2,3,4,5,6,7,8,9,10}     arr1.length = len1

arr2 = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}     arr2.length = len2

2.1 When 1 < = k < = 10 (1 < = k < = len1), assume k=6

Because k=6, < len1 & & < len2, the sixth smallest number can only appear in the first six numbers of the two arrays.

So we just need to call the function to find the upper median and pass in the first six digits of the two arrays

2.2 when 10 < K < 15 (len1 < K < len2), assume k=12

Because k=12, all numbers in arr1 are possible. In array arr2, 1 (the largest number is the 11th number) and 13-15 (the smallest number is 13-15) are impossible. Therefore, 2-12, a total of 11 numbers, meet the conditions, while the first array is 10 numbers. The lengths of the two arrays are different and the function number cannot be called. Therefore, it is necessary to manually judge a number, that is, 2 in arr2  

  • Arr2 [2] > = Arr1 [10]: arr[2] is the 12th number
  • Arr2 [2] < Arr1 [10]: the maximum number of arr[2] is the 11th. If it does not meet the requirements, it will be eliminated. Solve arr1[1-10],arr2[3-12]

After solving the upper median (the tenth) plus the two eliminated, it is exactly the twelfth number

2.3 when 15 < = k < = 25 (len2 < = k), assume k=20

Because k=20, the numbers before arr2[10] do not meet the requirements (when all elements in arr1 are pressed before arr2[10], arr2[10] can reach the 20th number, and the previous ones do not meet the requirements). Similarly, find out the ones that meet the conditions in arr1, that is

arr1[5]-arr1[10],arr2[10]-arr2[15], but when only the upper median of the two arrays is calculated, it will be found that 4 + 9 = 13 numbers have been eliminated before, and the median 6 = 19, not 20. Therefore, before calculating the upper median, it is necessary to judge whether the leftmost elements of the two arrays meet the requirements

  • arr1[5] > arr2 [15]: return to arr1[5]
  • arr2[10] > Arr1 [10]: return to arr2[10]
  • If they are not satisfied, solve arr1[6]-arr1[10],arr2[11]-arr2[15]

At this time, arr1 eliminated 5 numbers, arr2 eliminated 10 numbers, and the median 5 is exactly the 20th number

3 Coding

	public static int findKthNum(int[] arr1, int[] arr2, int kth) {
		if (arr1 == null || arr2 == null) {
			throw new RuntimeException("Your arr is invalid!");
		}
		if (kth < 1 || kth > arr1.length + arr2.length) {
			throw new RuntimeException("K is invalid!");
		}
		
		//Copy long array
		int[] longs = arr1.length >= arr2.length ? arr1 : arr2;
		//Copy short array
		int[] shorts = arr1.length < arr2.length ? arr1 : arr2;
		int l = longs.length;
		int s = shorts.length;
		//k is less than the short array length
		if (kth <= s) {
			return getUpMedian(shorts, 0, kth - 1, longs, 0, kth - 1);
		}
		//k is greater than the length of the long array
		if (kth > l) {
			//Determine whether the leftmost element of the short array that meets the condition is the desired element
			if (shorts[kth - l - 1] >= longs[l - 1]) {
				return shorts[kth - l - 1];
			}
			//Determine whether the leftmost element of the long array that meets the conditions is the desired element
			if (longs[kth - s - 1] >= shorts[s - 1]) {
				return longs[kth - s - 1];
			}
			//Find the upper median
			return getUpMedian(shorts, kth - l, s - 1, longs, kth - s, l - 1);
		}
		if (longs[kth - s - 1] >= shorts[s - 1]) {
			return longs[kth - s - 1];
		}
		return getUpMedian(shorts, 0, s - 1, longs, kth - s, kth - 1);
	}

	//To find the upper median, ensure that the two arrays are the same length
	public static int getUpMedian(int[] a1, int s1, int e1, int[] a2, int s2,
			int e2) {
		int mid1 = 0;
		int mid2 = 0;
		int offset = 0;
		while (s1 < e1) {
			mid1 = (s1 + e1) / 2;
			mid2 = (s2 + e2) / 2;
			offset = ((e1 - s1 + 1) & 1) ^ 1;
			if (a1[mid1] > a2[mid2]) {
				e1 = mid1;
				s2 = mid2 + offset;
			} else if (a1[mid1] < a2[mid2]) {
				s1 = mid1 + offset;
				e2 = mid2;
			} else {
				return a1[mid1];
			}
		}
		return Math.min(a1[s1], a2[s2]);
	}

        

Posted by ossi69 on Wed, 03 Nov 2021 22:27:41 -0700