[Data structure] LeetCode question of array: 88. Combine two ordered arrays, 4. Median of two positively ordered arrays

88. Combine two ordered arrays¹

Give you two ordered array of integers nums1 and nums2 , you will nums2 merged into nums1 in the nums1 become an ordered array.

Description:

  • Initialize the number of elements of nums1 and nums2 to m and n respectively .
  • You can assume that nums1 has enough space (the size of the space is greater than or equal to m + n ) to store the elements in nums2 .

Example:

输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6],       n = 3

输出: [1,2,2,3,5,6]

Solution 1: Merge first and then sort

  • Idea: Put nums2 into nums1 first, and then sort nums1
  • the complexity
    • Time: O(n*logn), based on sort
    • Space:O(1)
public void merge(int[] nums1, int m, int[] nums2, int n) {
    
    
        // 将nums2放入nums1
        for (int i = 0; i < n; i++) {
    
    
            nums1[i + m] = nums2[i];
        }
        // 排序
        Arrays.sort(nums1);
    }

Solution 2: Insert in reverse order

  • Idea: Since inserting in order requires moving the elements behind, then I can go backwards and insert from the back forward
  • the complexity
    • Time:O(m + n)
    • Space:O(1)
public void merge(int[] nums1, int m, int[] nums2, int n) {
    
    
    	// -1因为这里是索引
        int i = m - 1, j = n - 1, k = m + n - 1;
        while (i >= 0 && j >= 0) {
    
    
            if (nums1[i] > nums2[j]) 
                nums1[k--] = nums1[i--];
            else 
                nums1[k--] = nums2[j--];
        }
		// 注:不用判断i>=0的情况,因为要放入nums1,且nums1已经是有序的
        while (j >= 0) nums1[k--] = nums2[j--];
    }

4. The median of two positively ordered arrays³

Given two sizes m and n are positive sequence (small to large) arrays nums1and nums2.

Please find the median of these two positive arrays, and the time complexity of the algorithm is required to be O(log(m + n)).

You can assume nums1and nums2will not be both empty.

Example 1:

nums1 = [1, 3]
nums2 = [2]

则中位数是 2.0

Example 2:

nums1 = [1, 2]
nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

Solution one: merge

  • Idea: Combine nums1 and nums2 into an array, use the merge method in merge sort, and then return.
  • the complexity
    • Time: O (m + n), but the running time on LeetCode is the same as the next
    • Space:O(m + n)
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    
    
        int total = nums1.length + nums2.length;
        int[] tmp = new int[total]; // 创建一个新的大数组
        int i = 0, j = 0, k = 0;
    	// 核心!
        while (i < nums1.length && j < nums2.length) 
            tmp[k++] = nums1[i] <= nums2[j] ? nums1[i++] : nums2[j++];
    	// 处理未放入的情况
        while (i < nums1.length) tmp[k++] = nums1[i++];
        while (j < nums2.length) tmp[k++] = nums2[j++];

        if ((total & 1) == 1) return tmp[total/2];
    	// 注:这里一定要转成double,因为默认int会舍去除的结果
        else return (double)(tmp[total/2 - 1] + tmp[total/2])/2;
    }

Solution 2: Binary search*

  • the complexity
    • Time:O(log(m+n))
    • Space:O(1)
class Solution {
    
    
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    
    
        int total = nums1.length + nums2.length;
        if ((total & 1) == 1) {
    
    
            // 这里+1是表示要寻找第k小的的元素
            return findKthSmallestInSortedArrays(nums1, nums2, total/2 + 1);
        } else {
    
    
            double a = findKthSmallestInSortedArrays(nums1, nums2, total/2);
            double b = findKthSmallestInSortedArrays(nums1, nums2, total/2 + 1);
            return (a + b) / 2;
        }
    }

    // 寻找第K小的元素
    double findKthSmallestInSortedArrays(int[] nums1, int[] nums2, int k) {
    
    
        // len来表示结束条件, base记录基准索引
        int len1 = nums1.length, len2 = nums2.length, base1 = 0, base2 = 0;
        while (true) {
    
    
            // 结束条件:1.其中一个数组遍历完了  2.俩数组没走完,k走完了
            // 注:-1 是因为k表示的是第n小,这里要转换为索引
            if (len1 == 0) return nums2[base2 + k - 1];
            if (len2 == 0) return nums1[base1 + k - 1];
            if (k == 1) return Math.min(nums1[base1], nums2[base2]);

            // 寻找第k小:在nums1找k/2小, nums2找k-i小
            int i = Math.min(k/2, len1);
            int j = Math.min(k-i, len2);
            int a = nums1[base1 + i - 1];
            int b = nums2[base2 + j - 1];
		   // 找到k,且元素相等的情况
            if (i + j == k && a == b) return a;

            // 更新两数组中小的 base,len,k
            // 注:其中只有base是向后移动++,len和k都是--
            if (a <= b) {
    
    
                base1 += i;
                len1 -= i;
                k -= i;
            }
            if (a >= b) {
    
    
                base2 += j;
                len2 -= j;
                k -= j;
            }
        }
    }
}

Guess you like

Origin blog.csdn.net/weixin_43935927/article/details/108739020