一.移除元素
对于本题,共有两种解法:
思路一:创建新的数组,遍历原数组,将不为value的值放到新数组中,但本题不允许使用新的数组,因此该方法不行
思路二:使用快慢指针,原数组基础上进行修改,源数据、目标数据,分别用src和dst两个指针指向;src指向的值为value,则往后走,即++;若src指向的值不是value,则nums[dst]=nums[src],dst++,src++
注:value是我所需要删除的值
上图是初始化情况,创建两个变量,让他们指向数组的首地址;先判断src所指向元素是否为value(此处假设value为2),因为不是所以src++
src在++以后,因为指向了value,所以应该将dst指向的数组元素覆盖,换成src当前指向的value元素;在覆盖好以后,dst需要++,同时src也需要++
由上图可知,src遍历完整个数组就是循环终止的条件;同时循环结束以后,dst的值恰好是value值的数量,直接返回value
记忆方法:快慢指针各创一,没碰value快++,碰到value一起加
int removeElement(int* nums, int numsSize, int val) {
int src = 0, dst = 0;
while (src < numsSize) {
if (nums[src] == val) {
src++;
} else {
nums[dst] = nums[src];
dst++;
src++;
}
}
return dst;
}
上述代码解释:
先创建了两个变量,分别赋值为0(因为数组下标从0开始);while语句的结束条件是src越界,while语句里两种情况,一种是碰到value,一种没碰到(上文已经讲解过);最后返回dst,即value值个数
二.合并两个有序数组
对于本题,共有两种思路:
思路一:将nums2中数组依次放入到num1数组的后面,用排序算法对nums1进行排序(效率低下)
思路二:三指针,从后往前比较,比谁大,谁大谁往后放,l1和l2比较,谁大谁往l3放,放完的那个向前移动一位,l3也向前移动一位;并且如果L1先出循环,nums2中剩余数据应该存放到nums1中
创建三个变量,一个指向nums1数组的末端,一个指向nums1元素的末端,一个指向nums2数组的末端;如上图,l2>l1,因此l3所指向的位置存放6,存放完以后l3向前移动一位,l2向前移动一位,l1不动,以此类推
在l2走出数组以后,nums1数组已经完成了合并与排序工作;通过上图我们也不难发现,l1如果没有走出数组,但l2走出了数组,这种情况下已经完成了操作;这是因为l1中小的元素要比l2最小的首地址元素还要小,且l1作为有序数组,小的元素已经排好序了,因此不需要动
对于这种情况,l1>l2,因此l3指向的内容存放6;存放完l1往前移动一位,l3往前移动一位,l2不动,以此类推
可是这种情况,在l1走出循环以后,nums2数组里依旧有一个数字1并未存放到nums1数组中;这时就需要循环语句讲nums2中的剩余元素合并到nums1数组中,请注意l2和l1一起减一的关系不变
记忆方法:两个指最后,一个指当中;最后当中比大小,谁大谁放最后;大的指向要--,存放位置也--;若没存放完,循环语句放进去,--关系不能变
void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n) {
int l1 = m - 1; // nums1[]已经存放好的元素
int l3 = m + n - 1; // nums1[]的总长度
int l2 = n - 1; // nums2[]存放的元素
while (l1 >= 0 && l2 >= 0) {
if (nums1[l1] < nums2[l2]) {
nums1[l3--] = nums2[l2--];
} else {
nums1[l3--] = nums1[l1--];
}
}
while (l2 >= 0) {
nums1[l3--] = nums2[l2--];
}
}
上述代码解释:
创建三个变量,分别指向三个位置;while语句,分l1>l2和l1<l2两种情况;--是后置--,先使用后--;循环结束以后如果nums2里还有数据没存放,循环语句放进去