
合并两个有序数组,这道题拿到后,第一时间你可能会想到把nums2的元素全部插入到nums1数组中,然后再调用排序函数,但其实这种极度暴力的方法是不可取的,因为题目已经说了,两个数组都是有序的,你这样做相当于直接浪费掉这么一个便利条件,那可能你会想,那就用两个指针分别指向nums1数组和nums2数组的首元素,然后分别比较然后再放置呗,但其实这种思路只能说是对一部分,你不要忘记,这里用的是数组而非链表,在数组内部做元素的插入是相当麻烦的,你需要大量频繁地移动数组元素,得不偿失。
那应该怎么做呢?其实我前边也提醒过了,之所以说这道题对一部分是因为我们可以从后往前找大元素,数组头插中间插入困难,那我们避其锋芒执行尾插不就好了吗。

这是一张示意图,如你所见,我们用到了三个指针,分别指向nums1,nums2数据的末尾位置,nums1的末尾位置,之所以还要有n3是因为我们需要为新数据的插入指定位置,因为你从后往前找大肯定是先找到最大的放在最后,放置了一个元素在末尾后肯定就不能接着尾插了,所以需要这么一个指针来指向相应的插入位置。
具体的思路是,n1与n2比较大小,大的放在n3,n3--,大的指针--,然后循环往复,直至一方为NULL,当一方为NULL时,证明这个数组的元素已经重新插入完成了,此时我们要做的就是将另一个数组的元素从后往前放到n3的位置,n3同样需要--
不过虽然我们这里说指针为NULL,但其实这只是一个伪指针,实践中是可以用数组的下标代替指针达到理想效果的。
接着要来说关于边境情况的处理,首先nums1题目规定是不能为空的,那么假设nums2为空,那直接返回nums1即可,假设nums2不为空且nums1里只有一个0,即nums1的数据域是没有元素的,那我们直接放到nums1哪一个位置后返回即可,代码如下
cpp
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
int p1,p2,p3=0;
p3=m+n-1;
p2=n-1;
p1=m-1;
if(p3==0)
{
if(p2==0)
nums1[0]=nums2[p2];
}
else
{
while(p1>=0&&p2>=0)
{
if(nums1[p1]<nums2[p2])
{
nums1[p3]=nums2[p2];
p2--;
}
else
{
nums1[p3]=nums1[p1];
p1--;
}
p3--;
}
while(p2>=0)
{
nums1[p3]=nums2[p2];
p3--;
p2--;
}
}
}
好的下一题

这道题思路是什么?你可能第一反应是遍历数组,遇到一个值为val的元素就删除,但是删除在数组中也是十分麻烦的,涉及到大量元素的移动,那不妨我们可以试一试下面这种写法。
即用两个指针,p1,p2初始都指向首元素,p1代表当前待插入的位置,p2则负责往后遍历数组,当p2遇到不为val的值时将其放到p1中p1++p2++,遇到为val的值直接跳过,最后当p2遍历完成后,p1即为元素个数
具体代码实现如下
cpp
int removeElement(int* nums, int numsSize, int val) {
int p1=0;
int p2=0;
while(p2<numsSize)
{
if(nums[p2]!=val)
{
nums[p1]=nums[p2];
p1++;
}
p2++;
}
return p1;
}