领扣网算法学习笔记
本系列的算法题目来自领扣网
数组类算法第二天
题目:
给定一个数组 *nums *和一个值 val,你需要原地移除所有数值等于 *val *的元素,返回移除后数组的新长度。
不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
示例:
给定 nums = [3,2,2,3], val = 3,
函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。
给定 nums = [0,1,2,2,3,0,4,2], val = 2,
函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。
解题思路:
思路一:
按照上一篇的思路,第一感觉就是,定义一个变量,初始值为0,然后判断,如果不为指定值则将值赋给以该变量作为位置的数组值,然后该变量+1,最后新数组的长度就是该变量的值。
class Solution {
public int removeElement(int[] nums, int val) {
int nonValIndex = 0;
for(int i=0;i<nums.length;i++){
if(nums[i] != val){
nums[nonZeroIndex++]=nums[i];
}
}
return nonValIndex;
}
}
// 用时9ms左右
后续思考:
这解题思路和5ms的思路一致,只是把自增放到了赋值里面就这样了,以后要把自增从赋值语句中拿出来。
领扣上面该题其他高质量范例:
class Solution {
public int removeElement(int[] nums, int val) {
int begin = 0;
if (nums.length == 0) {
return 0;
} else if (nums.length == 1) {
if (nums[0] == val) {
return 0;
} else {
return 1;
}
}
int end = nums.length - 1;
while (begin < end) {
//找到目前第一个值为val的元素
while (nums[begin] != val && begin < end) {
begin++;
}
//从后面找到第一个值不为val的元素
while (nums[end] == val && begin < end) {
end--;
}
if (begin != end) {
int tmp = nums[begin];
nums[begin] = nums[end];
nums[end] = tmp;
} else {
if (nums[begin] != nums[end]){
return end + 1;
}else{
if(nums[end] == val){
return end;
}
return end + 1;
}
}
}
return end;
}
}
// 用时6ms
自我整理:
这部分代码思路我没有想到,且这部分代码有一个我很喜欢的点,也是我目前欠缺的点,就是在执行代码前对条件进行判断,避免出现了因为条件根本就不满足直接导致循环主要代码执行出现异常。
这题的思路如下:
- 将从头开始遍历得到的第一个指定值的位置 与 从尾反向遍历得到第一个不是指定值的位置的值进行交换,直到数组全部遍历完。
- 这样得到的数组前面部分是非指定值,后面部分是指定值,
- 新数组的长度就是前面部分的长度。
自我总结:
平时一定要养成良好的习惯,编写代码时,要对传入的参数进行数据的判断,避免因传入的数据错误,或者是空值导致出现程序异常或者Bug。判断的同时就可以实现解决方法。