An intuitive way to do it

If you think about it in terms of “KTH decimal” it’s pretty obvious: find the “median place” decimal. With double Pointers, whichever array has the smallest value moves the pointer back one bit. But you have to iterate to the median, O(m+n)O(m+n)O(m+n)

215. The KTH largest element in an array

[Method 1] dichotomy

I’ve understood the dichotomy of chicken for a long time… There is a tricky method for handling odd and even lengths: Find (m + n + 12) \ left (\ frac {m + n + 1} {2} \ right) (m + 2 n + 1) and (m + n + 22) \ left (\ frac {m + n + 2} {2} \ right) (m + 2 n + 2) location (round down) the Numbers on the additive/again 2. Because for an odd number, these two values are the same. Ps: It feels like this approach can be reused for other similar scenarios


Let’s do it! First of all, we have two arrays A and B, respectively take A A \ [k2-1] left [\ frac {k} \ right] {2} – 1-1] [2 k and B B \ [k2-1] left [\ frac {k} \ right] {2} – 1 B – 1] [2 k value. Compare these two values, such as the B to B \ [k2-1] left [\ frac {k} \ right] {2} – 1 B / 2 k – 1 > A \ [k2-1] left [\ frac {k} {2} – 1 \ right] A [2 k – 1), to analyze the wave: Note that we are now focusing on the (k2)\left(\frac{k}{2}\right)(2k) values before both arrays. Because they add up to k, the KTH number can only happen between them. B[k2−1]B\left[\frac{k}{2}-1\right]B[2k−1] is the largest of the k numbers. The k is either after (k2)\left(\frac{k}{2}\right)(2k) or before (k2)\left(\frac{k}{2}\right)(2k)), So the front (k2)\left(\frac{k}{2}\right)(2k) of array A can be discarded. Next, find the first (k4)\left(\frac{k}{4}\right)(4k) values of the two arrays… Recurse until the KTH value is left.


(^o^)/ (^o^)/ (^o^)/ (^o^

Attached with dish chicken solution (performance is not very good, to be optimized)

function result(arr, len1, len2){
    return (arr[Math.floor((len1 + len2 + 1) / 2) - 1] + arr[Math.floor((len1 + len2 + 2) / 2) - 1) /2;
}

var findMedianSortedArrays = function(nums1, nums2) {
    if(! nums1.length){// The other array is 0
        return result(nums2, 0, nums2.length);
    }
    if(! nums2.length){return result(nums1, 0, nums1.length);
    }
    letisOdd = !! ((nums1.length + nums2.length) %2); 
    // target: the number of numbers to the left of the line
    let target = Math.ceil((nums1.length + nums2.length)/2);
    // prevent undefined when looking for i-1 or j-1
    nums1[-1] = -1000000;
    nums2[-1] = -1000000;
    nums1.push(1000000);
    nums2.push(1000000);
    let i = Math.floor(target / 2);
    let j = target - i;
    // Make sure the initial Pointers have values
    while(nums1[i] === undefined){
        i--;
        j++;
    }
    while(nums2[j] === undefined){
        i++;
        j--;
    }
    / / main logic
    while(nums1[i] ! = =undefined&& nums2[j] ! = =undefined) {if (nums1[i] >= nums2[j - 1] && nums2[j] >= nums1[i - 1]) {return isOdd ? Math.max(nums2[j - 1], nums1[i - 1]) : (Math.max(nums2[j - 1], nums1[i - 1]) + Math.min(nums1[i], nums2[j])) / 2
        }
        if(nums1[i] < nums2[j - 1]){
            i++;
            j--;
        }
        if(nums2[j] < nums1[i - 1]){ i--; j++; }}if(! nums1[i]){return isOdd ? nums2[target - 1] : (nums2[target - 1] + nums2[target]) / 2;
    } 
    if(! nums2[j]){return isOdd ? nums1[target - 1] : (nums1[target - 1] + nums1[target]) / 2; }}Copy the code

Ps: there have been a ray, often on chang xin — while (nums1 [I] && nums2 [j]) to empty, can cause error when array has a value of 0.

[method 2] Use a Quicksort partition

The essence of quicksort is to continuously rearrange the base, so you can directly find the number in the middle according to the position of the number rearranged each time.

review

I didn’t quite understand that sort is a process of constantly “rearranging” elements, except that bubble sort is a process of constantly “rearranging” large numbers, whereas sort is a process of constantly rearranging the current base number. Why does the base number return? When we keep moving the Pointers around, swapping values greater than and less than the base, and finally putting the base where the Pointers meet, we guarantee that the left side of base is less than it and the right side is greater than it, and that’s where it stays when the array is ordered. When we pick a base at random, we do the same thing, moving from both ends to the center, selecting, swapping, and then pushing the base to the center of the contradiction.

let arr = [1.3.4.2.3];
// n1 and n2 are subscripts of the numbers to be swapped
function swap(arr, n1, n2) {
  let temp = arr[n1];
  arr[n1] = arr[n2];
  arr[n2] = temp;
}

function qs(arr, start, end) {
  if (start >= end) {
    return;
  }
  let i = start;
  let j = end;
  while (i < j) {
    // Since the leftmost value is the base value, so find the small value first
    // This is done in case the leftmost value is the minimum value. If you look for the maximum value, you will find the second value
    // End up with [1] and [2] swapped
    
    // Look for small values from right to left
    while (i < j && arr[j] >= arr[start]) {
      j--;
    }
    // From left to right, continue when you reach a small value.
    while (i < j && arr[i] <= arr[start]) {
      i++;
    }
    if (i < j) {
      swap(arr, i, j);
    }
    // i++ or j-- is unnecessary
    // Because we need I to "bump" into j (I === j)
    // It is unnecessary to swap elements incorrectly
  }
  swap(arr, start, i);
  qs(arr, start, i - 1);
  qs(arr, i + 1, end);
}
qs(arr, 0, arr.length - 1); // [1, 2, 3, 3, 4]
Copy the code

If k is greater than base, then we only need to look in the interval (base, end). If k is greater than base, then we only need to look in the interval (base, end). If k is greater than base, then we only need to look in the interval (base, end). They can always be found. In this case, when the size of the median is settled, we need to find two bases, and the time when the two bases are settled is unknown

How are JS parameters passed?

There is only one rule for parameter passing: pass by value, copy based on value. The primitive type copies the value itself, so the two copies do not affect each other; Reference types copy reference values, so parameters and arguments refer to the same object. If an object is modified by one reference, the object accessed by the other reference is the modified object. Swap should be written like this (I tried to take arr[n1] and arr[n2] as arguments at first…). :

let arr = [1.3.4.2.3]
// n1 and n2 are subscripts of the numbers to be swapped
function swap(arr, n1, n2) {
  let temp = arr[n1];
  arr[n1] = arr[n2];
  arr[n2] = temp;
}
Copy the code