思路:头双指针、尾双指针
头双指针
对比于队列,队列是先进先出,由于我们遇到的是两个有序数组。所以,对于两个数组,我们只需要依次分别判断两个数组的头指针位置所指的元素大小,将小的元素先放入数组中。由于题目要求将新的数组放在nums1中,所以,使用头指针直接将元素放入到nums1中,会把nums1中的元素覆盖。解决方法:新开辟一个地址空间,大小为nums1的大小,用于暂时存储排序后的数组,最后for循环赋值。
对于思路很好理解,具体的实现方法,到自己手上又等了很久才想到。主要是逐步运算过程中出现的一些情况处理;普通的情况就是,nums1[i]与nums2[j]大小对比;哪个小,那个就放进数组中;但是在运算过程中,总会出现一个数组的值全部处理完之后的结果。所以需要加入判断条件:if(i == m),if(j == n);这时候的一个情况处理。
具体看代码:
//正向双指针解法
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
//nums1Size和nums2Size是不需要用到的,迷惑我们的
//我刚开始用了nums1Size,一直报错
int i = 0, j = 0, a=0; //a是新数组的下标值
//新开辟的地址空间用于存储处理后的数组
int sorted[m+n];
while(i < m || j < n){
//首先要判断nums1和nums2数组是否已经全部遍历
if(i == m){
sorted[a++] = nums2[j++];
}else if(j == n){
sorted[a++] = nums1[i++];
//这里是原本的双指针处理方法
}else if(nums1[i] < nums2[j] ){
sorted[a++] = nums1[i++];
}else{
sorted[a++] = nums2[j++];
}
//sorted[i+j-1] = a;
}
//for循环给nums1进行赋值
for(i = 0; i != m+n; ++i){
nums1[i] = sorted[i];
}
}
尾双指针
从头指针可以发现对nums1来说,需要重新开辟一个新的地址空间。尾双指针可以解决这个问题。因为nums1后m个位置为空,所以,可以利用nums1尾部没有利用到的空间进行,那这里使用尾双指针。
思路
跟头双指针的思路基本一致,仍然需要对一个数组已经遍历完的情况进行处理。
**注意点:**对于nums1下标值的处理,刚开始我是直接使用的nums1[i+j-1];后来发现一直报错,缓存溢出,找了很久没找到错误,跟正确答案对比了之后,发现自己的下标值其实是错的,因为 i 和 j 都已经减了1,再去用nums1的尾指针指向值不是最后一个,所以要修改一下
具体看代码:
//逆向双指针解法
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n){
int i = m-1, j = n-1, a;
int tail = n + m -1;
while(i >= 0 || j >= 0){
if(i == -1){
a = nums2[j--];
}else if(j == -1){
a = nums1[i--];
}else if(nums1[i] < nums2[j] ){
a = nums2[j--];
}else{
a = nums1[i--];
}
//注意不能用首位双指针的方法进行i+j-1
//前面,i, j 都已经减1,然后运行过程中又减了一个1,所以需要+2
//或者是nums1[tail--] = a;
nums1[i+j+2] = a;
}
}