移除元素
题目1:删除有序数组中的重复元素
要求:重复元素只出现一次,最后返回新数组的长度,不能使用额外的数组,必须原地修改,仅使用O(1)的额外空间。
解题思路:双指针法
首先我们可以定义两个指针,一个快指针,一个慢指针。慢指针初始位置在nums[0],快指针初始位置在nums[1]。然后比较两个指针所在位置对应的值,如果相等,则快指针后移一位,慢指针不动;如果不相等,就把快指针当前值赋值给慢指针后一位,然后慢指针后移一位…直到快指针遍历完原始数组为止。最后返回 慢指针下标+1。
本人代码:
class Solution {
public int removeDuplicates(int[] nums) {
int i = 0;
for (int j = 1; j < nums.length; j++) {
if (nums[i] != nums[j]) {
nums[i+1] = nums[j];
i++;
}
}
return i+1;
}
}
如果看代码比较抽象的话,可以画图来理解,同时也可以检测代码是否正确
题目2:移除数组中指定的元素
要求: 去掉数组中所有的指定元素,不能使用额外的数组空间,仅使用O(1)的空间并原地修改数组,最后返回新数组的长度,元素顺序可以更改
解题思路:
方法一:双指针法
这种方法跟上面那题几乎是一样,只要拿捏好两个指针的下标就行,这里不再赘述,给出AC代码。
class Solution {
public int removeElement(int[] nums, int val) {
int i = 0;
for (int j = 0; j < nums.length; j++) {
if (val != nums[j]) {
nums[i] = nums[j];
i++;
}
}
return i;
}
}
方法二:双指针之互换元素法
简单讲一下这种方法,这种方法其实也是双指针,但它是更为效率的双指针。举个简单的例子:假定给出的数组为nums[1,2,3,4,5],val = 5,此时按方法一求解的话是做了一些无用的赋值操作的。相当于前四个元素都做了一遍自身赋值给自身的过程,方法二就是为了解决这个弊端。
我们可以这么想,当nums[i] == val时,我们把nums中最后一个元素赋值给nums[i],并把最后一个元素释放掉;如果nums[i] != val,就仅仅让i++,不进行重新赋值的过程
这里给出AC代码
public int removeElement(int[] nums, int val) {
int i = 0;
int n = nums.length;
while (i < n) {
if (nums[i] == val) {
nums[i] = nums[n - 1];
// 并把数组长度减一
n--;
} else {
i++;
}
}
return n;
}
这里面有几个地方解释一下
1.while(i < n )这里面i < n 的条件是因为,i是下标,n是长度,下标一定要小于长度
2.第一个if里面不能对下标i做数值加减操作,是因为要验证数组最后一位值是否为题目中所要的val
3.最后返回n,是因为换元素的过程中数组末尾元素没有去掉,但我们取长度为n的数组即为题目所要的新数组
写在最后
题目较为简单,大佬请略过,本人只是为了梳理所学的知识,仅做总结。