初版代码:
存在问题如下
-
循环边界问题:在循环中,你使用了一个索引变量
i
来遍历数组nums
,但在循环体内部又定义了一个新的索引变量index
并且增加了它的值。这可能导致你在数组范围之外访问内存,可能会引发未定义行为。 -
---index作为int类型,其本身数值增减并不会导致错误,但我用index来当计步器,记录将若*p1==val时之后位置找到的第一个*p2值的位置;但这里忘了一个问题就是for循环是重复numsSize次数的,而随着每次移除元素,newlengs新的数组长度会减少,那么定义index=i+1;就会发生数组越界,指针将移动未定义区域的内存空间。
-
指针操作问题:在内层循环中,你使用指针
p2
来查找连续的相同值,并将其替换为下一个不同的值。但是,在进行指针操作时,没有检查是否超出了数组边界。这可能导致指针越界访问,从而引发内存访问错误。 -
循环中的内存操作:在循环的最后部分,你使用指针
p2
和tmp
进行数组元素的移动操作。然而,在移动元素之前,没有检查指针是否超出了数组边界。这可能导致在移动元素时访问了无效的内存位置。
int removeElement(int* nums, int numsSize, int val){
int*p1,*p2;
p1=p2=nums;
int newlens=numsSize;//记录剩余长度
for (int i=0; i<numsSize; i++) {
int index=i+1;
if(*p1==val)
{
p2=p1+1;
index++;
while (*p2==val) {
p2++;
index++;//找到p1后第一个不为val的位置
}
*p1=*p2;//p2替换p1的值
for (int j=0; j<newlens-index;j++) {
int*tmp=p2+1;
*p2=*tmp;
tmp++;
p2++;
}//数组前移完毕
newlens--;
}
p1++;
}
return newlens;
}
修改之后的代码:
int removeElement(int* nums, int numsSize, int val) {
int* p1 = nums;
int* p2 = nums;
int newLength = numsSize;
for (int i = 0; i < numsSize; i++) {
if (*p1 == val) {
p1++;
newLength--;
} else {
*p2 = *p1;
p1++;
p2++;
}
}
return newLength;
}
修改思路如下:
-
使用两个指针
p1
和p2
分别指向原始数组中的元素。p1
用于遍历数组中的元素,而p2
用于指示下一个不等于目标值的位置。 -
当
p1
指向的元素等于目标值时,将p1
向后移动一位,而newLength
减一表示忽略一个重复的元素。 -
当
p1
指向的元素不等于目标值时,将该元素复制到p2
的位置,同时将p1
和p2
都向后移动一位。 -
最后返回新长度
newLength
。
--我使用的是暴力算法,在找到第一个目标元素时,就将后续数组挨个前移覆盖;同样是双指针,一个指针用于遍历数组,另外一个指针用于将元素前移。时间复杂度为O(n^2)
时间复杂度更低的是“快慢指针方法”
快慢指针遍历数组
如果不是目标元素,指针同时前移;
当遇到目标元素,慢指针停下,快指针前移,直到遇到第一个不为目标元素的内存空间,将*p2=*p1后lens--;快慢指针再前移。当p1遍历完数组后,慢指针所在位置就是新数组结束的位置,下标也对应着新的数组长度。