力扣题目链接:https://leetcode.cn/problems/remove-element/
要点:
数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
暴力解法:
两层for循环,一个for循环遍历数组元素,一个for循环更新数组。
代码如下:
class Solution {
public int removeElement(int[] nums, int val) {
int size = nums.length;
for(int i = 0; i<size; i++){
if(nums[i] == val){
for(int j = i+1 ;j <size ;j++){
nums[j-1] = nums[j];
}
i--;// 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
size--;// 此时数组的大小-1
}
}
return size;
}
}
-
时间复杂度:O(n^2)
-
空间复杂度:O(1)
双指针法(快慢指针法):
通过一个快指针和慢指针在一个for循环下完成两个for的工作。
-
快指针:寻找新数组的元素(不包含目标值元素的数组)
-
慢指针:指向更新 新数组下标的位置
代码如下:
class Solution {
public int removeElement(int[] nums, int val) {
int slowIndex = 0;
for(int fastIndex = 0; fastIndex < nums.length; fastIndex++){
if(nums[fastIndex] != val){
nums[slowIndex] = nums[fastIndex];
slowIndex++;
}
}
return slowIndex;
}
}
-
时间复杂度:O(n),其中 n 为序列的长度。我们只需要遍历该序列至多两次。
-
空间复杂度:O(1)。我们只需要常数的空间保存若干变量。
相向双指针法:
避免了要保留的元素重复赋值操作
如果要移除的元素恰好在数组的开头,例如序列 [1,2,3,4,5],当 val 为 1 时,我们需要把每一个元素都左移一位。注意到题目中说:「元素的顺序可以改变」。实际上我们可以直接将最后一个元素 5 移动到序列开头,取代元素 1,得到序列 [5,2,3,4],同样满足题目要求。这个优化在序列中 val 元素的数量较少时非常有效。
class Solution {
public int removeElement(int[] nums, int val) {
int left = 0;
int right = nums.length-1;
while(left <= right){
if(nums[left] == val){
nums[left] = nums[right];
right--;
}else{
left++;
}
}
return left;
}
}
-
时间复杂度:O(n),其中 n 为序列的长度。我们只需要遍历该序列至多一次。
-
空间复杂度:O(1)。我们只需要常数的空间保存若干变量。
1693

被折叠的 条评论
为什么被折叠?



