给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1)
额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
- 暴力解
思想:原地移除,遍历一次数组,当遇到val时,将往后的整体往前移动一位,长度减少1;
时间复杂度:O(n^2),空间复杂度为1。
public int removeElement(int[] nums, int val) {
//暴力解法
/**
* 原地移除数组中target元素 原地移除
* 整体移除元素
*
* 时间复杂度:O(n^2)
* 空间复杂度:O(1)
* @param nums
* @param val
* @return
*/
int resLength = nums.length;
for (int i = 0; i < resLength; i++) {
// 发现需要移除的元素,就将数组集体向前移动一位
if (nums[i]==val) {
for (int j = i + 1; j < resLength; j++) {
nums[j-1] = nums[j];
}
// 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
i--;
//数组大小减一
resLength--;
}
}
return resLength;
}
- 双指针
public int removeElement(int[] nums, int val) {
/**
* 双指针
* 时间复杂度:O(n)
* 时间复杂度:O(1)
* @param nums
* @param val
* @return
*/
int slowIndex = 0;
int fastIndex = 0;
for (;fastIndex < nums.length;fastIndex++){
if (val != nums[fastIndex]){
nums[slowIndex++] = nums[fastIndex];
}
}
return slowIndex;
}
- 相向双指针
public int removeElement(int[] nums, int val) {
int leftIndex = 0;
int rightIndex = nums.length - 1;
while (leftIndex <= rightIndex){
//寻找左边的目标值val
while (leftIndex <= rightIndex && val != nums[leftIndex] ){
leftIndex++;
}
//寻找右边非目标值,等于目标值往前移动一位 直到不等于val 且 rightIndex >= leftIndex
//此处逻辑不能写 反,&&短路与必须是先满足 rightIndex >= leftIndex 否则会出现数组越界情况
while (rightIndex >= leftIndex && val == nums[rightIndex]){
--rightIndex;
}
//进行交换
if (leftIndex < rightIndex){
// int tem = nums[leftIndex];
// nums[leftIndex] = nums[rightIndex];
// nums[rightIndex] = tem;
nums[leftIndex++] = nums[rightIndex--];
}
}
return leftIndex;
}