暴力解法:
- 时间复杂度:O(n^2);空间复杂度:O(1)。
代码:
int removeElement(int* nums, int numsSize, int val){
int temp = numsSize;
for(int i = 0; i < numsSize; i ++){
if(nums[i] == val) temp --;
}
for(int j = 0; j < temp; j ++){//遍历前(temp)个元素,后面的不用,因为在遍历前已经将val放过去了
if(nums[j] == val){
for(int k = j + 1; k < numsSize; k ++){
if(nums[k] != val){
nums[j] = nums[k];
nums[k] = val;
break;
}
}
}
}
return temp;
}
虽然力扣可以通过,但是还能快些。
双指针法(快慢指针法):
- 快指针用来寻找可替换(前移)元素;
- 慢指针用来更新数组并记录最终输出的数组长度;
- 时间复杂度:O(n);空间复杂度:O(1)。
动图解释:
代码:
int removeElement(int* nums, int numsSize, int val){
int fastIndex = 0;//定义快指针
int slowIndex = 0;//定义慢指针
for(; fastIndex < numsSize; fastIndex ++){//快指针遍历数组
if(nums[fastIndex] != val){//当快指针所指元素不是val时,则对慢指针赋予快指针所指元素
/*nums[slowIndex] = nums[fastIndex];
slowIndex ++;这个会慢,用下面那种写法*/
nums[slowIndex ++] = nums[fastIndex];
}
//当快指针元素指的是val时,往后移一位
}
return slowIndex;
}
补充:相向双指针方法(确保元素替换次数最少)
有个小知识点在里边——&&的执行看前后顺序
int removeElement(int* nums, int numsSize, int val){
int leftIndex = 0;//定义左指针
int rightIndex = numsSize - 1;定义右指针
while(leftIndex < rightIndex){
/*while(nums[leftIndex] != val && leftIndex < rightIndex) {
leftIndex ++;
}
while(nums[rightIndex] == val && leftIndex < rightIndex){
rightIndex --;
}*/
//&&的执行看前后的,所以必须先判断是否越界,再去查看对应数组中的值
while(leftIndex < rightIndex && nums[leftIndex] != val) {//找到左边的val
leftIndex ++;
}
while(leftIndex < rightIndex && nums[rightIndex] == val){//找到右边可替换的值
rightIndex --;
}
if(leftIndex < rightIndex){//判断后对左边赋值,并且指针各向中间移一位
nums[leftIndex ++] = nums[rightIndex --];
}
}
return leftIndex + 1;//返回的是长度
}