移除元素|刷题打卡

91 阅读2分钟

本文正在参与掘金团队号上线活动,点击 查看大厂春招职位

一、题目描述:

image.png

image.png

二、思路分析:

今天给大家分享的是一道简单题。 先看题,题目给定我们一个数组和一个值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 双指针来交换左右位置的值。