zoukankan      html  css  js  c++  java
  • [LeetCode] 88. 合并两个有序数组

    Description

    给你两个有序整数数组nums1nums2,请你将nums2合并到nums1中,使nums1成为一个有序数组。

    说明:

    初始化nums1nums2的元素数量分别为mn
    你可以假设nums1有足够的空间(空间大小大于或等于 m + n)来保存nums2中的元素。

    示例:

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

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/merge-sorted-array
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    Analyse

    合并两个有序数组nums1和nums2,nums1的空间够放下nums2,不用开新的数组存结果

    归并排序(Merge sort)

    完整版的归并排序在这里不是最优解,因为数组的两部分已经有序了,可以直接双指针法开始merge,但这道题是个练习归并排序的好地方

    class Solution {
        public void merge(int[] nums1, int m, int[] nums2, int n) {
            // 先将 nums2 append 到 nums1
            // public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)
            System.arraycopy(nums2, 0, nums1, nums1.length - nums2.length, nums2.length);
            int low = 0, high = nums1.length - 1;
    
            // merge sort
            mergeSort(nums1, low, high);
        }
    
        // 将数组拆分成两部分,直到有序
        private void mergeSort(int[] nums, int low, int high) {
            // base case
            if (low >= high) return;
    
            int mid = low + (high - low) / 2; // 不用(low + high) / 2 防止加法溢出
    
            mergeSort(nums, low, mid);
            mergeSort(nums, mid+1, high);
    
            merge(nums, low, mid, high);
        }
    
        // 合并两个有序数组(或数据的两个有序部分)
        private void merge(int [] nums, int low, int mid, int high) {
            // 双指针法
            int p = low, q = mid + 1;
    
            // 需要一个临时空间
            int[] tmpNums = new int[high - low + 1];
            int index = 0;
            while (p <= mid && q <= high) {
                if (nums[p] < nums[q]) {
                    tmpNums[index++] = nums[p++];
                } else {
                    tmpNums[index++] = nums[q++];
                }
            }
    
            while (p <= mid) {
                tmpNums[index++] = nums[p++];
            }
    
            while (q <= high) {
                tmpNums[index++] = nums[q++];
            }
    
            // 将排好序的值写回nums
            System.arraycopy(tmpNums, 0, nums, low, high - low + 1);
        }
    }
    

    将merge()改成下面这样就能击败100%了,时间复杂度O(n + m);空间复杂度O(n + m),空间复杂度还可以继续优化,只需要把nums1中的元素复制出来一份就行了O(m),再继续优化可以两个有序数组逆序比较,这样只需要O(1)

    public void merge(int[] nums1, int m, int[] nums2, int n) {
        // 先将 nums2 append 到 nums1
        System.arraycopy(nums2, 0, nums1, m, n);
    
        // int low = 0, high = m - 1;
    
        // merge sort
        // mergeSort(nums1, low, high);
        merge(nums1, 0, m - 1, m + n - 1);
    }
    
  • 相关阅读:
    去掉FALSH背景的代码
    问一个比较傻瓜的问题关于 this.TextBox1.Visible = true;
    网页防止复制 下载 另存为的JS
    [转] left join/right join/inner join操作演示
    VS2003新起项目步骤
    我专严新闻小偷之心得与大家交流
    ACCESS数据库里SQL语句的3个表联合,和SQL有很大差别
    vs2005常用快捷键
    NoSql中的CAP分类【转载】
    epoll用法【整理】
  • 原文地址:https://www.cnblogs.com/arcsinw/p/13218237.html
Copyright © 2011-2022 走看看