leetcode:27
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
基础:
1.数组为空和数组长度为0的区别?
int[] n; //只声明了一数组变量;
int[] nil = null; //声明一数组变量,并赋值 null,nil是一个数组类型的空引用,不指向任何对象;
int[] zero = new int[0]; //声明并创建一数组对象,长度是0;
数组为空,数组不指向任何对象;数组长度为0,定义一个长度为0的数组;
长度为0,已经是new出来的,占用了内存地址。在堆中已经有内存;
2.数组的元素在内存地址中是连续的,不能单独删除数组中的某个元素,只能覆盖。
思路:
把重复的值与数组的末尾值交换,没有考虑到数组对称的情况;
[3,2,2,3],删除3,只删除头的一个元素
收获:
必须先预先写出不满足条件的要返回的值。
不用交换数组元素,根据统计的新数组的长度,可以在已经判断的数组的基础上数组覆盖;
快慢指针指的是:j 慢指针;i 快指针
刷题总结:
二刷:
新数组的长度len,就是for循环中的len,不用加1;
测试一:错误思路,未考虑数组对称,
class Solution {
public int removeElement(int[] nums, int val) {
int j=nums.length-1;//j意味着数组的最后的不重复元素
for(int i =0 ;i<=j;i++){
if(nums[i]==val){
//交换val到数组的最后
int t = val;
val = nums[j];
nums[j] = t;
j--;
}
}
return j+1;
}
}
正确解法:快慢指针,数组覆盖
class Solution {
public int removeElement(int[] nums, int val) {
if(nums==null || nums.length == 0){
return 0;
}
//定义记录数组长度的变量
int j =0;
for(int i=0;i<nums.length;i++){
//数组直接覆盖,借助原数组,因为i之前是已经判断的,可以直接覆盖
if (nums[i] != val){
nums[j]=nums[i];
j++;
}
}
return j;
}
}