移除元素

发布时间 2024-01-07 17:23:52作者: lulixiu

移除元素

第一种:暴力双循环

#include <stdio.h>

int removeElement(int* nums, int size, int val) {
int newSize = size;
for (int i = 0; i < newSize; i++) {
if (nums[i] == val) {
for (int j = i + 1; j < newSize; j++) {
nums[j - 1] = nums[j];
}
i--;//为了确保下一次循环仍然考虑到当前位置,我们将i减1,这样下一轮循环会继续在之前的位置开始检查。
newSize--;
}
}
return newSize;//只返回了大小,但是数组也通过指针变了,不需要返回
}

int main() {
int nums[] = { 3, 2, 2, 3 }; // 示例输入数组
int val = 3; // 要移除的元素
int size = sizeof(nums) / sizeof(nums[0]); // 数组的大小

int newSize = removeElement(nums, size, val); // 调用移除函数

// 输出移除元素后的数组
printf("New Array: ");
for (int i = 0; i < newSize; i++) {
printf("%d ", nums[i]);
}
printf("\n");

// 输出移除元素后的数组大小
printf("New Size: %d\n", newSize);

return 0;
}

第二种:双指针(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

定义快慢指针

快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组

慢指针:指向更新 新数组下标的位置,找到了就自己挪动

代码如下

int removeElement(int* nums, int numsSize, int val) {
int slow = 0;
for (int fast = 0; fast < numsSize; fast++) {
if (nums[fast] != val) {////若快指针位置的元素不等于要删除的元素
nums[slow++] = nums[fast]; //将其挪到慢指针指向的位置,慢指针+1
}
}
return slow;//最后慢指针的大小就是新的数组的大小
}

趣味记忆

int removeElement(int* nums, int numsSize, int val) {
int slow = 0, fast = 0; //一对夫妇,原本都是零起点
while (fast < numsSize) {   //但是有一个跑得快,一个跑得慢
if (nums[fast] != val) {//于是跑得快的那个先去寻找共同目标
nums[slow] = nums[fast];//如果找到了,就送给跑得慢的那个
slow++; //然后跑得慢的那个也就离目标近一点
}
fast++; //但是不管是否找得到,跑得快的那方都一直奔跑到生命的尽头
}
return slow;//最终留下跑得慢的一方
}

算法优化

如果左指针 left指向的元素等于 val,此时将右指针 right 指向的元素复制到左指针 left 的位置,然后右指针 right 左移一位。如果赋值过来的元素恰好也等于val,可以继续把右指针 right 指向的元素的值赋值过来,左指针 left 指向的等于 val 的元素的位置继续被覆盖),直到左指针指向的元素的值不等于 val 为止。

当左指针 left 和右指针 right 重合的时候,左右指针遍历完数组中所有的元素。

这样的方法两个指针在最坏的情况下合起来只遍历了数组一次。与方法一不同的是,方法二避免了需要保留的元素的重复赋值操作。

int removeElement(int* nums, int numsSize, int val) {
int left = 0, right = numsSize;
while (left < right) {
if (nums[left] == val) {
nums[left] = nums[right - 1];
right--;
} else {
left++;
}
}
return left;
}