本文正在参与掘金团队号上线活动,点击 查看大厂春招职位
一、题目描述:
二、思路分析:
今天给大家分享的是一道简单题。 先看题,题目给定我们一个数组和一个值val,要求我们原地删除数组中所有值等于val的元素,并且返回移除后数组的新长度,不能使用额外的空间。元素的顺序可以改变。 OK,一个能想到的思路是双指针的思路,一个快指针遍历元素,一个慢指针放置符合要求的元素。因此下面的代码1就是我今天写的.....明明是easy,却写出了这么一坨,竟然AC.
- 简洁的写法。还是双指针的思路,快指针只负责遍历新的元素,当新的元素不是val时,直接赋给慢指针,然后慢指针往前走。遍历一遍即可。如代码2
- 更优化的双指针。考虑一下情况,nums=[1,2,3,4,5],val=1。如果我们使用上面的方法,那么对于2,3,4,5,我们每个都要移动一次。因为题目中说最后输出元素的顺序可以改变,所以我们还是使用双指针,left,right,分别指向数组首尾位置,当两个指针未相遇的时候,如果左指针指向的元素等于val,那么我们直接交换left,right 的值,然后right --。就算交换过去的right还是val,我们也是不怕的。因为right已经左移了,下一次还会把她交换走。当循环结束left == right,此时还要判断一下 left 位置的值是否是val,如果是val,那么返回left即可,如果不是val,返回left+1;
三、AC 代码:
//代码1
function removeElement(&$nums, $val) {
$len_n = count($nums);
$index = 0;
$i = 0;
while ($i < $len_n) {
if ($nums[$i] != $val) {
$nums[$index] = $nums[$i];
$index++;
$i++;
} else {
$j = $i + 1;
while ($j < $len_n && $nums[$j] == $nums[$i]) {
$j++;
}
if ($j < $len_n) {
$nums[$index] = $nums[$j];
$index++;
$i = $j + 1;
} else {
break;
}
}
}
return $index;
}
//代码2
function removeElement(&$nums, $val) {
$len_n = count($nums);
$fast = 0;
$slow = 0;
for ($fast = 0; $fast < $len_n; $fast++) {
if ($nums[$fast] != $val) {
$nums[$slow++] = $nums[$fast];
}
}
return $slow;
}
//代码3
function removeElement(&$nums, $val) {
$len_n = count($nums);
if ($len_n == 1 && $nums[0] == $val) {
return [];
}
$left = 0;
$right = $len_n - 1;
while ($left < $right) {
if ($nums[$left] == $val) {
$nums[$left] = $nums[$right];
$right--;
} else {
$left++;
}
}
return $nums[$left] == $val ? $left : $left + 1;
}
四、总结:
今天的题目要求我们原地修改数组,一般遇到这种情况都可以考虑双指针的情况,一个快指针往前走遍历元素,一个慢指针指向所有满足条件的元素位置。本题由于题目中说了返回元素顺序可以变化,引导我们使用left, right 双指针来交换左右位置的值。