Merge Sorted Array

Problem

You are given two integer arrays nums1 and nums2, sorted in non-decreasing order, and two integers m and n, representing the number of elements in nums1 and nums2 respectively.

Merge nums1 and nums2 into a single array sorted in non-decreasing order.

The final sorted array should not be returned by the function, but instead be stored inside the array nums1. To accommodate this, nums1 has a length of m + n, where the first m elements denote the elements that should be merged, and the last n elements are set to 0 and should be ignored. nums2 has a length of n.

Example 1:

Input: nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
Output: [1,2,2,3,5,6]
Explanation: The arrays we are merging are [1,2,3] and [2,5,6].
The result of the merge is [1,2,2,3,5,6] with the underlined elements coming from nums1.

Example 2:

Input: nums1 = [1], m = 1, nums2 = [], n = 0
Output: [1]
Explanation: The arrays we are merging are [1] and [].
The result of the merge is [1].

Example 3:

Input: nums1 = [0], m = 0, nums2 = [1], n = 1
Output: [1]
Explanation: The arrays we are merging are [] and [1].
The result of the merge is [1].
Note that because m = 0, there are no elements in nums1. The 0 is only there to ensure the merge result can fit in nums1.

Constraints:

  • nums1.length == m + n
  • nums2.length == n
  • 0 <= m, n <= 200
  • 1 <= m + n <= 200
  • -109 <= nums1[i], nums2[j] <= 109

Follow up: Can you come up with an algorithm that runs in O(m + n) time?

Solution

This problem has a twist because it has to be done in-place.

We can do it in O(m + n) time by swapping.

e.g.

nums1 = [1,2,3,0,0,0] nums2 = [2,5,6]

keep a counter for nums1 called p1, nums2 called p2.

check if nums[p1] < nums[p2]. if so increment p1 else, swap nums[p1] with nums[p2]. increment p2

continue until p1 and p2 reach the end of the respective array

no extra space, and done in O(m + n).


My approach didn’t work for the example 4, 5, 6, 0, 0, 0, 1, 2, 3.

The issue is that we would swap 4 -> 2 which breaks the sorting.

We need to sort from the end rather than the beginning to avoid this issue.

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        var cm = m - 1;
        var cn = n - 1;
        var c = m + n - 1;

        // we're essentially starting at the logical ends of nums1 and nums2. we make a local decision and copy the largest value into the slot at c until we've rewritten the entire nums1 array.
        // there's a lot of trickiness with indexes, off-by-one errors, etc.
        while (c >= 0) {
            // check that both arrays are still valid OR that at least nums1 is valid
            if ((cm >= 0 && cn >= 0 && nums1[cm] > nums2[cn]) || (cm >= 0 && cn < 0)) {
                // pull from nums1
                nums1[c] = nums1[cm];
                cm -= 1;
            } else {
                // pull from nums2
                nums1[c] = nums2[cn];
                cn -= 1;
            }
            c -= 1;
        }
    }
}

Recent posts from blogs that I like

Sequoia introduces pinning to iCloud Drive

If you have Optimise Mac Storage enabled for iCloud Drive, this new feature lets you pin the files you want to be stored locally and not evicted. Full details.

via The Eclectic Light Company

Notes on running Go in the browser with WebAssembly

Recently I've had to compile Go to WebAssembly to run in the browser in a couple of small projects (#1, #2), and in general spent some time looking at WebAssembly. I find WebAssembly to be an exciting technology, both for the web and for other uses (e.g. with WASI); specifically, it's pretty great t...

via Eli Bendersky

I fixed the strawberry problem because OpenAI couldn't

Remember kids: real winners cheat

via Xe Iaso