和并两个有序数组(双指针法)
介绍
本篇博客介绍了双指针法在合并两个有序数组中的应用,以及以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
- 比较array1[i]和array2[j]的大小:
- array1[0] = 1
- array2[0] = 2
- 因为1小于2,所以将1添加到result中,并将i指针向后移动一位。
- result = [1, _, _, _, _, _, _, _]
- i = 1
- 接下来,再次比较array1[i]和array2[j]的大小:
- array1[1] = 3
- array2[0] = 2
- 因为3大于2,所以将2添加到result中,并将j指针向后移动一位。
- result = [1, 2, _, _, _, _, _, _]
- j = 1
- 再次进行比较:
- array1[1] = 3
- array2[1] = 4
- 因为3小于4,所以将3添加到result中,并将i指针向后移动一位。
- result = [1, 2, 3, _, _, _, _, _]
- i = 2
- 继续比较:
- array1[2] = 5
- array2[1] = 4
- 因为5大于4,所以将4添加到result中,并将j指针向后移动一位。
- result = [1, 2, 3, 4, _, _, _, _]
- j = 2
- 再次进行比较:
- array1[2] = 5
- array2[2] = 6
- 因为5小于6,所以将5添加到result中,并将i指针向后移动一位。
- result = [1, 2, 3, 4, 5, _, _, _]
- i = 3
- 继续比较:
- array1[3] = 7
- array2[2] = 6
- 因为7大于6,所以将6添加到result中,并将j指针向后移动一位。
- result = [1, 2, 3, 4, 5, 6, _, _]
- j = 3
- 继续比较:
- 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的范围。
- 将: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的末尾)
进入循环比较阶段:
- 因为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
- 继续下一次循环:
- 比较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
- 继续下一次循环:
- 比较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
- 继续下一次循环:
- 比较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--];
}
}