📝思路一:常规双指针
不是说nums1的数组长度是m+n吗?
所以一开始我是想直接把nums2的元素按大小添加到nums1中😂
但在添加过程我发现如果直接将nums1和nums2中元素的值进行比较,按大小顺序添加到nums1里,这样是会把原来nums1中的元素 给覆盖掉的,所以我就直接把nums1中合并前的元素复制到了tmp数组中
然后设置两个双指针,分别指向各种数组的起始位置,通过这两个双指针不断的对tmp数组和nums2数组进行大小比较,再依次放到nums1数组中
🌰代码如下:
class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { int[] tmp = new int[m]; for (int i = 0; i < m; ++i) tmp[i] = nums1[i]; // 将nums1合并前的元素复制到tmp数组中 int p = 0, q = 0, k = 0; while ( p < m && q < n) { if (tmp[p] <= nums2[q]) { // 如果tmp[p]小,先把tmp[p]放到nums1中 nums1[k] = tmp[p]; ++k; ++p; } else { nums1[k] = nums2[q]; ++k; ++q; } } while (p < m) { // 当nums2中的数组合并完了,直接把tmp数组中剩下的元素依次放到nums1就行 nums1[k] = tmp[p]; ++k; ++p; } while (q < n) { nums1[k] = nums2[q]; ++k; ++q; } } }
📝思路二:逆序双指针
我们上面那种思路为了防止nums1中的元素被覆盖,用到了额外的数组
🍑但分析题目后我们发现:nums1后边都是0,如果我们把比较后的元素放到nums1的后边,也就是把元素从后往前的放到nums1中(这样不就避免了元素覆盖吗😁)
💡同时我们也应该注意到,既然是把元素从后往前的放到nums1中,那么我们一开始找到肯定这两个数组中最大的元素
💡所以说我们的两个指针,一开始就应该就应该从各种数组中有效元素的结尾出发,然后让他们两两的进行比较求得较大的那个。
💡之后大的继续前移,小的不动,之后再和大的那个元素的前一个进行比较
代码:
class Solution { public void merge(int[] nums1, int m, int[] nums2, int n) { // 两个指针分别从各自数组的最末尾的一个有效元素出发 int i = m - 1, j = n - 1, k = n + m - 1; // 从后往前遍历这样nums1的元素不会被覆盖 while (i >= 0 && j >= 0) { if (nums1[i] > nums2[j]) { nums1[k] = nums1[i]; --i; --k; } else { nums1[k] = nums2[j]; --j; --k; } } // 如果此时i 还大于0,不用管,因为本来就是把数组合并到nums1中,只用考虑j就行 while (j >= 0) { nums1[k] = nums2[j]; --j; --k; } } }