首页 > 编程语言 >LeetCode算法笔记 88. 合并两个有序数组

LeetCode算法笔记 88. 合并两个有序数组

时间:2022-10-09 23:55:23浏览次数:52  
标签:p2 p1 int 复杂度 88 nums1 算法 LeetCode nums2

import junit.framework.TestCase;

import java.util.Arrays;

public class LeetCode02_2 extends TestCase {

    /**
     * 88. 合并两个有序数组
     * 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。
     * 请你 合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序 排列。
     * 注意:最终,合并后数组不应由函数返回,而是存储在数组 nums1 中。为了应对这种情况,nums1 的初始长度为 m + n,其中前 m 个元素表示应合并的元素,后 n 个元素为 0 ,应忽略。nums2 的长度为 n 。
     * <p>
     * 示例 1:
     * 输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
     * 输出:[1,2,2,3,5,6]
     * 解释:需要合并 [1,2,3] 和 [2,5,6] 。
     * 合并结果是 [1,2,2,3,5,6] ,其中斜体加粗标注的为 nums1 中的元素。
     * <p>
     * 示例 2:
     * 输入:nums1 = [1], m = 1, nums2 = [], n = 0
     * 输出:[1]
     * 解释:需要合并 [1] 和 [] 。
     * 合并结果是 [1] 。
     * <p>
     * 示例 3:
     * 输入:nums1 = [0], m = 0, nums2 = [1], n = 1
     * 输出:[1]
     * 解释:需要合并的数组是 [] 和 [1] 。
     * 合并结果是 [1] 。
     * 注意,因为 m = 0 ,所以 nums1 中没有元素。nums1 中仅存的 0 仅仅是为了确保合并结果可以顺利存放到 nums1 中。
     * <p>
     * 提示:
     * nums1.length == m + n
     * nums2.length == n
     * 0 <= m, n <= 200
     * 1 <= m + n <= 200
     * -109 <= nums1[i], nums2[j] <= 109
     * <p>
     * 进阶:你可以设计实现一个时间复杂度为 O(m + n) 的算法解决此问题吗?
     */

    /**
     * 方法一:直接合并后排序
     * 时间复杂度:O((m+n)log(m+n))。
     * 排序序列长度为 m+nm+n,套用快速排序的时间复杂度即可,平均情况为 O((m+n)log(m+n))。
     *
     * 空间复杂度:O(log(m+n))。
     * 排序序列长度为 m+n,套用快速排序的空间复杂度即可,平均情况为 O(log(m+n))。
     */
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        for (int i = 0; i < n; i++) {
            nums1[m + i] = nums2[i];
        }
        Arrays.sort(nums1);
        System.out.println("merge -> " + Arrays.toString(nums1));
    }

    /**
     * 方法二:双指针
     * 时间复杂度:O(m+n)。 指针移动单调递增,最多移动 m+n 次,因此时间复杂度为 O(m+n)。
     * 空间复杂度:O(m+n)。需要建立长度为 m+n 的中间数组 res。
     */
    public void merge2(int[] nums1, int m, int[] nums2, int n) {
        int[] res = new int[m + n];
        int p1 = 0, p2 = 0;
        for (int i = 0; i < (m + n); i++) {
            if (p1 == m) {
                res[i] = nums2[p2++];
            } else if (p2 == n) {
                res[i] = nums1[p1++];
            } else if (nums1[p1] < nums2[p2]) {
                res[i] = nums1[p1++];
            } else {
                res[i] = nums2[p2++];
            }
        }
        for (int i = 0; i < res.length; i++) {
            nums1[i] = res[i];
        }
        System.out.println("merge2 -> " + Arrays.toString(nums1));
    }

    /**
     * 方法二:双指针
     * 时间复杂度:O(m+n)。 指针移动单调递增,最多移动 m+n 次,因此时间复杂度为 O(m+n)。
     * 空间复杂度:O(m+n)。需要建立长度为 m+n 的中间数组 res。
     */
    public void merge3(int[] nums1, int m, int[] nums2, int n) {
        int[] res = new int[m + n];
        int p1 = 0, p2 = 0;
        int tmp;
        while (p1 < m || p2 < n) {
            if (p1 == m) {
                tmp = nums2[p2++];
            } else if (p2 == n) {
                tmp = nums1[p1++];
            } else if (nums1[p1] < nums2[p2]) {
                tmp = nums1[p1++];
            } else {
                tmp = nums2[p2++];
            }
            res[p1 + p2 - 1] = tmp;
        }

        for (int i = 0; i < res.length; i++) {
            nums1[i] = res[i];
        }
        System.out.println("merge3 -> " + Arrays.toString(nums1));
    }

    /**
     * 方法三:逆向双指针
     * 时间复杂度:O(m+n) 指针移动单调递减,最多移动 m+n 次,因此时间复杂度为 O(m+n)。
     * 空间复杂度:O(1) 原地修改,不需要额外空间。
     */
    public void merge4(int[] nums1, int m, int[] nums2, int n) {
        int p1 = m - 1, p2 = n - 1;
        for (int i = (m + n - 1); i >= 0; i--) {
            if (p1 == -1) {
                nums1[i] = nums2[p2--];
            } else if (p2 == -1) {
                nums1[i] = nums1[p1--];
            } else if (nums1[p1] > nums2[p2]) {
                nums1[i] = nums1[p1--];
            } else {
                nums1[i] = nums2[p2--];
            }
        }
        System.out.println("merge4 -> " + Arrays.toString(nums1));
    }

    /**
     * 方法三:逆向双指针
     * 时间复杂度:O(m+n) 指针移动单调递减,最多移动 m+n 次,因此时间复杂度为 O(m+n)。
     * 空间复杂度:O(1) 原地修改,不需要额外空间。
     */
    public void merge5(int[] nums1, int m, int[] nums2, int n) {
        int p1 = m - 1, p2 = n - 1;
        int tmp;
        while (p1 > -1 || p2 > -1) {
            if (p1 == -1) {
                tmp = nums2[p2--];
            } else if (p2 == -1) {
                tmp = nums1[p1--];
            } else if (nums1[p1] > nums2[p2]) {
                tmp = nums1[p1--];
            } else {
                tmp = nums2[p2--];
            }
            nums1[p1 + p2 + 2] = tmp;
        }
        System.out.println("merge5 -> " + Arrays.toString(nums1));
    }

    public void test01() {
        int[] nums1 = {1, 2, 3, 0, 0, 0};
        int[] nums2 = {2, 5, 6};
        merge5(nums1, 3, nums2, 3);
        int[] nums3 = {1};
        int[] nums4 = {};
        merge5(nums3, 1, nums4, 0);
        int[] nums5 = {0};
        int[] nums6 = {1};
        merge5(nums5, 0, nums6, 1);
    }
}

标签:p2,p1,int,复杂度,88,nums1,算法,LeetCode,nums2
From: https://www.cnblogs.com/sueyyyy/p/16774162.html

相关文章

  • 算法1-c# dotnet core3.1
    usingSystem;namespaceConsoleApp1{classProgram{staticvoidMain(string[]args){Console.WriteLine("HelloWorld!");......
  • 华为招聘|自动驾驶感知、融合、预测、PNC、SLAM算法及深度学习算法研究员等岗位
    技术改变世界,梦想成就自我校园招聘专场             --华为2012实验室.自动驾驶团队·招聘信息:对象:海外/国内优秀高校博士及海外硕士。(团队国内......
  • 算法1-Java
    importjava.util.Date;classTest{publicstaticvoidmain(String[]args){longt1=newDate().getTime();for(inta=0;a<1001;a++){......
  • LeetCode算法笔记 1. 两数之和
    publicclassLeetCode02_1extendsTestCase{/***1.两数之和*给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值tar......
  • 牛客网高频算法题系列-BM18-二维数组中的查找
    牛客网高频算法题系列-BM18-二维数组中的查找题目描述在一个二维数组array中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺......
  • KMP 算法 再次学习
    c++版后面再补packagecn.kbug.dynamic;importjava.util.Arrays;/***KMP算法本质上是对搜索的字符串做优化,然后在匹配的时候,能做到非常省时间*如果搜索的串......
  • Raft 共识算法:全貌
    转载请注明出处:https://www.cnblogs.com/morningli/p/16768025.htmlRaft基础raft集群由若干server组成,典型的集群包含5个server,这样可以允许两个server发生故障。这些s......
  • Leetcode 11 -- 双指针&&贪心
    题目说明盛水最多的容器题目要求我们找出两个边界\(L\)和\(R\),使得容量:\(min(right[L],right[R])*(R-L)\)的值最大。思路算法不是玄学。首先,两层for循......
  • 排序算法
    排序算法选择排序:先将数列完完全全检索一边,然后选出最小的数与最左边数字替换;接着从第二个数字开始再检索整个数列,选出最小的数字后与第二个数字替换,以此类推;重复步骤1......
  • 排序算法
    选择排序#include<stdio.h>intmain(){inti,j,t,a[9];//定义变量及数组为基本整型printf("请输入8个数:\n");for(i=1;......