和并两个有序数组(双指针法)LeetCode88题

和并两个有序数组(双指针法)

介绍

本篇博客介绍了双指针法在合并两个有序数组中的应用,以及以LeetCode88题为例,展示了逆向双指针的用法。双指针法是一种常用的算法技巧,通过使用两个指针分别指向两个有序数组的起始位置,可以实现将两个有序数组合并为一个有序数组的操作。

在讲解过程中,首先介绍了双指针法的基本原理,即通过比较两个指针所指向元素的大小,将较小的元素添加到新数组中,并将相应的指针向后移动。然后,通过具体的代码示例,展示了双指针法合并两个有序数组的实现过程。在示例中,通过两个指针分别指向array1和array2的起始位置,比较两个指针所指向元素的大小,并将较小的元素添加到新数组中,同时将相应的指针向后移动,直到其中一个指针超出数组范围。最后,将另一个数组中剩余的元素依次添加到新数组中,即可得到合并后的有序数组。

接着,介绍了LeetCode88题的要求和函数头,即合并两个有序数组。根据题目要求,采用逆向双指针的方法进行求解。逆向双指针的思想是从后往前遍历数组,比较两个指针所指向元素的大小,将较大的元素放入新数组的末尾,并将相应的指针向前移动。循环比较直到其中一个指针小于0,然后将另一个指针中剩余的元素放入新数组的前面。最后,得到合并后的有序数组。

通过这篇博客的介绍,读者可以了解到双指针法在合并两个有序数组中的应用,以及逆向双指针的具体实现方法。同时,通过LeetCode88题的例子,读者可以进一步掌握双指针法在实际问题中的应用。希望这篇博客能够对读者有所帮助!如果还有其他问题,请随时提问。

讲解:双指针法合并两个有序数组

代码:合并

public static int[] myMergeSortedArrays(int[] array1, int[] array2) {
        int len1=array1.length;
        int len2=array2.length;
        int[]arr=new int[len1+len2];
        int i=0,j=0,k=0;
        while(i<len1&&j<len2){
            //小的数先进新数组
            if(array1[i]>array2[j]){
                arr[k]=array2[j++];
            }else{
                arr[k]=array1[i++];
            }
            k++;
        }
        while(i<len1){
            arr[k++]=array1[i++];
        }
        while(j<len2){
            arr[k++]=array2[j++];
        }
        return arr;
    }

合并的过程演示

public static void main(String[] args) {
        int[] array1 = {1, 3, 5, 7};
        int[] array2 = {2, 4, 6, 8};
        int[] result = myMergeSortedArrays(array1, array2);

        System.out.print("Merged Array: ");
        for (int num : result) {
            System.out.print(num + " ");
        }
    }

首先,我们有两个有序数组:
array1 = [1, 3, 5, 7]
array2 = [2, 4, 6, 8]
我们创建一个新数组result,长度为array1.length + array2.length。
result = [_, _, _, _, _, _, _, _]

现在,我们使用两个指针i和j分别指向array1和array2的起始位置。
i = 0
j = 0

  1. 比较array1[i]和array2[j]的大小:
  • array1[0] = 1
  • array2[0] = 2
  • 因为1小于2,所以将1添加到result中,并将i指针向后移动一位。
  • result = [1, _, _, _, _, _, _, _]
  • i = 1
  1. 接下来,再次比较array1[i]和array2[j]的大小:
  • array1[1] = 3
  • array2[0] = 2
  • 因为3大于2,所以将2添加到result中,并将j指针向后移动一位。
  • result = [1, 2, _, _, _, _, _, _]
  • j = 1
  1. 再次进行比较:
  • array1[1] = 3
  • array2[1] = 4
  • 因为3小于4,所以将3添加到result中,并将i指针向后移动一位。
  • result = [1, 2, 3, _, _, _, _, _]
  • i = 2
  1. 继续比较:
  • array1[2] = 5
  • array2[1] = 4
  • 因为5大于4,所以将4添加到result中,并将j指针向后移动一位。
  • result = [1, 2, 3, 4, _, _, _, _]
  • j = 2
  1. 再次进行比较:
  • array1[2] = 5
  • array2[2] = 6
  • 因为5小于6,所以将5添加到result中,并将i指针向后移动一位。
  • result = [1, 2, 3, 4, 5, _, _, _]
  • i = 3
  1. 继续比较:
  • array1[3] = 7
  • array2[2] = 6
  • 因为7大于6,所以将6添加到result中,并将j指针向后移动一位。
  • result = [1, 2, 3, 4, 5, 6, _, _]
  • j = 3
  1. 继续比较:
  • array1[3] = 7
  • array2[3] = 8
  • 因为7小于8,所以将7添加到result中,并将i指针向后移动一位。
  • result = [1, 2, 3, 4, 5, 6, 7, _]
  • i = 4

此时,i指针超出了array1的范围,但j指针还没有超出array2的范围。

  1. 将:array2中的元素放入新数组中
  • 将array2[3] = 8添加到result中,并将j指针向后移动一位。
  • result = [1, 2, 3, 4, 5, 6, 7, 8]
  • j = 4

此时,i和j指针都超出了各自数组的范围。

最终得到合并后的有序数组:
result = [1, 2, 3, 4, 5, 6, 7, 8]

LeetCode练习88. 合并两个有序数组

题目
题目给的函数头

public void merge(int[] nums1, int m, int[] nums2, int n) {
        
}

提示:这里的m和n分别代表两个数组中的有效元素。
例:{1,2,3,0,0,0}
这个数组的有效元素为3,实际长度为6。

讲解:逆向双指针

通过使用两个指针进行逆序遍历,可以避免对nums1中的元素进行移动,从而达到不使用额外空间的要求。(将两个数组的元素都存储在第一个数组中,看题目提示)

让我一步一步地看看这两个数组的合并过程:

初始状态:
nums1: [1, 3, 5, 7, 0, 0, 0, 0]
nums2: [2, 4, 6, 8]

首先,我们定义三个指针:

p = 2 (指向nums1的最后一个非零元素)
q = 3 (指向nums2的最后一个元素)
k = 7 (指向nums1的末尾)

进入循环比较阶段:

  1. 因为p和q都大于等于0,所以进入循环。
  • 比较nums1[p]和nums2[q],发现nums2[q] = 8较大,将其放入nums1[k]位置,同时将指针q减1: nums1: [1, 3, 5, 7, 0, 0, 0, 8]
  • 将指针k减1: k = 6
  • 此时的状态为: nums1: [1, 3, 5, 7, 0, 0, 0, 8] nums2: [2, 4, 6, 8] p = 2, q = 2, k = 6
  1. 继续下一次循环:
  • 比较nums1[p]和nums2[q],发现nums1[p] = 7较大,将其放入nums1[k]位置,同时将指针p减1: nums1: [1, 3, 5, 7, 0, 0, 7, 8]
  • 将指针k减1: k = 5
  • 此时的状态为: nums1: [1, 3, 5, 7, 0, 0, 7, 8] nums2: [2, 4, 6, 8] p = 1, q = 2, k = 5
  1. 继续下一次循环:
  • 比较nums1[p]和nums2[q],发现nums1[p] = 5较大,将其放入nums1[k]位置,同时将指针p减1: nums1: [1, 3, 5, 5, 0, 0, 7, 8]
  • 将指针k减1: k = 4
  • 此时的状态为: nums1: [1, 3, 5, 5, 0, 0, 7, 8] nums2: [2, 4, 6, 8] p = 0, q = 2, k = 4
  1. 继续下一次循环:
  • 比较nums1[p]和nums2[q],发现nums2[q] = 6较大,将其放入nums1[k]位置,同时将指针q减1: nums1: [1, 3, 5, 5, 0, 6, 7, 8]
  • 将指针k减1: k = 3
  • 此时的状态为: nums1: [1, 3, 5, 5, 0, 6, 7, 8] nums2: [2, 4, 6, 8] p = 0, q = 1, k = 3

循环结束后,p已经小于0,说明nums1中的元素已经全部比较完毕。现在只需要将nums2中剩余的元素放入nums1对应位置即可:

  • 将nums2中剩余的元素[2, 4]依次放入nums1[0]和nums1[1]的位置: nums1: [1, 2, 3, 4, 5, 6, 7, 8]

最终合并完毕后的nums1为:[1, 2, 3, 4, 5, 6, 7, 8]。

希望这样的步骤展示对您有所帮助!如果还有其他问题,请随时提问。

代码:解LeetCode88题

public void merge(int[] nums1, int m, int[] nums2, int n) {
    int p = m - 1;     
    int q = n - 1;     
    int k = nums1.length - 1;   
    // 将nums1和nums2中元素按照非递减顺序合并到nums1中
    while (p >= 0 && q >= 0) {
        nums1[k--] = nums1[p] > nums2[q] ? nums1[p--] : nums2[q--];                   
    }
	// 如果q仍大于等于0,则继续将nums2中剩余的元素放入nums1中
    while (q >= 0) {
        nums1[k--] = nums2[q--];
    }
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值