首页 > 编程语言 >力扣面试经典算法150题:移除元素

力扣面试经典算法150题:移除元素

时间:2024-08-10 18:58:40浏览次数:9  
标签:150 nums 元素 链表 力扣 数组 移除 指针

移除元素

今日的题目依旧是力扣面试经典算法150题中数组相关的题目:移除元素

题目链接:https://leetcode.cn/problems/remove-element/description/?envType=study-plan-v2&envId=top-interview-150

题目描述

给定一个排序数组 nums 和一个值 val,需要在原地移除数组中所有等于val 的元素,并返回移除后数组的新长度。不需要考虑超出新长度以外的元素。

  • 注意:
    • 必须在原地修改输入数组,不能使用额外的数组空间。
    • 元素的顺序可以改变,你不需要考虑数组中超出新长度后面的元素。
  • 示例:
    • 输入:
      nums = [3,2,2,3], val = 3
    • 输出:
      新长度为 2,数组变为 [2,2](注意:返回值为新长度,数组内容可以不是连续的)
  • 解释:
    • 数组 nums 中的值 3 被移除了两次。
    • 移除后的新数组长度为 2,数组内容为 [2,2]。

题目分析

题目要求我们在不使用额外空间的情况下,移除数组中的特定元素,并返回移除后的数组长度。

为了达到 O(1) 的额外空间复杂度,这要求我们需要在原地修改数组。

解题思路

题目的要求就两个,一个移出元素,一个将不同的元素放到原本的数组中。这就意味着我们需要在一个循环中进行两种操作,这里很容易就会想到用双指针来完成,一个指针拿出元素比较,一个指针将元素放入数组,并且这个指针最后停留的下标就是最后一个不同的元素。

实际算法代码

根据以上分析和思路,我们可以写出以下代码:

import java.util.Arrays;

/**
 * description
 *
 * @author 明月望秋思
 * @date 2024/8/6 
 */
public class RemoveElement {
    /**
     * 移除数组中的指定元素
     *
     * @param nums 输入数组
     * @param val  需要移除的值
     * @return 移除后的新数组长度
     */
   public int removeElement(int[] nums, int val) {
        // 指针1,用于遍历数组比较元素
        int i = 0;
        // 指针2,用于记录新数组的下标位置
        int j = 0;

        // 遍历数组
        while (i < nums.length) {
            // 比较元素是否与val相等
            if (nums[i] != val) {
                nums[j] = nums[i];
                // 只有元素不同时,才放入元素并更新指针2
                j++; 
            }
            // 更新指针1,不管元素是否相同,都要向下遍历
            i++; 
        }
		// 返回新数组的长度,因为在循环中进行了++的操作
        return j; 
    

    public static void main(String[] args) {
        RemoveElement solution = new RemoveElement();

        // 示例数据
        int[] nums = {3, 2, 2, 3};
        int val = 3;

        // 调用移除方法
        int newLength = solution.removeElement(nums, val);

        // 输出新长度和移除后的数组
        System.out.println("New length: " + newLength);
        System.out.println("Modified array: " + Arrays.toString(Arrays.copyOfRange(nums, 0, newLength)));
    }
}

提交代码,测试通过。

在这里插入图片描述

因为算法用到了双指针,下面讲一下双指针法的内容。

双指针法

双指针法是一种常用的算法技巧,它通过使用两个指针来遍历数据结构(如数组或链表),以简化问题的解决过程。

使用场景

双指针法适用于多种场景,下面列举了一些常见的使用双指针法的场景及其原因:

  • 在原数组对象操作数组
    • 场景描述:不增加额外空间复杂度度的情况下完成对数组的操作。
    • 原因:双指针法可以直接在原数组上进行操作,可以减少不必要的比较和浪费额外的空间。
  • 寻找两个数使它们的和为特定值
    • 场景描述:给定一个有序数组,找到数组中两个数,使它们的和等于特定的目标值。
    • 原因:有序数组允许我们使用双指针从两端向中间逼近,一个指针从头部开始,另一个从尾部开始。这样可以避免不必要的比较,提高效率。
  • 快速排序中的分区操作
    • 场景描述:在快速排序算法中,需要选择一个基准值,并将小于基准值的元素放在左边,大于基准值的元素放在右边。
    • 原因:双指针可以帮助我们有效地进行分区操作,一个指针从左向右移动,另一个从右向左移动,当两个指针指向的元素不符合分区规则时,交换它们的位置。
  • 求解回文子串
    • 场景描述:给定一个字符串,判断它是否是回文串,或者找出最长的回文子串。
    • 原因:对于回文串,中心对称的特性使得我们可以使用双指针从中心向两边扩展来检查字符串是否为回文。
  • 求解链表的中间节点
    • 场景描述:给定一个单链表,需要找到链表的中间节点。
    • 原因:使用快慢指针,快指针每次移动两步,慢指针每次移动一步,当快指针到达链表尾部时,慢指针正好位于中间。
  • 反转链表
    • 场景描述:给定一个链表,需要反转链表的顺序。
    • 原因:使用双指针技巧,一个指针指向当前节点,另一个指针指向当前节点的前一个节点,通过调整指针方向来实现反转。
  • 滑动窗口
    • 场景描述:在数组或字符串中找到满足特定条件的最大或最小子序列。
    • 原因:双指针可以用来定义滑动窗口的边界,一个指针作为窗口的起始位置,另一个指针作为窗口的结束位置,随着遍历,动态调整窗口大小以满足条件。
  • 寻找重复元素
    • 场景描述:在有序数组中查找重复元素。
    • 原因:使用双指针技巧,一个指针从头开始,另一个指针从尾开始,根据元素的大小关系移动指针来寻找重复项。
  • 合并两个有序数组
    • 场景描述:给定两个有序数组,需要将它们合并成一个新的有序数组。
    • 原因:使用双指针从后向前比较两个数组的元素,并将较大的元素放入结果数组的末尾,可以保证合并后的数组仍然是有序的。
  • 检测链表中的环
    • 场景描述:给定一个链表,需要检测链表中是否存在环。
    • 原因:使用快慢指针技巧,快指针每次移动两步,慢指针每次移动一步,如果存在环,快指针最终会追上慢指针。

双指针法之所以在这些场景中有效,是因为它能够减少不必要的比较次数,提高算法的时间效率,并且在很多情况下能够避免使用额外的空间,从而达到 O(1) 的空间复杂度。

双指针法的优点:

双指针法有以下优点:

  • 原地修改:不需要额外的空间来存储新数组,直接在原数组上进行修改,这样就可以在 O(1) 的额外空间复杂度下完成移除操作。
  • 保持有序性:在移除元素的过程中,可以使有效元素仍然保持有序。
  • 效率高:只需要遍历一次数组即可完成移除操作,时间复杂度为 O(n)。
  • 简单易实现:双指针法的逻辑简单,易于理解和实现

总结

实际上上一篇文章中的题目,也是用的双指针法。

双指针法在处理数组的算法题时,是比较常见且又好用的一种解决办法。

熟练使用可以更好的帮助在数组方面的问题!

标签:150,nums,元素,链表,力扣,数组,移除,指针
From: https://blog.csdn.net/weixin_48668564/article/details/140948892

相关文章

  • 151. 反转字符串中的单词【 力扣(LeetCode) 】
    一、题目描述  给你一个字符串s,请你反转字符串中单词的顺序。  单词是由非空格字符组成的字符串。s中使用至少一个空格将字符串中的单词分隔开。  返回单词顺序颠倒且单词之间用单个空格连接的结果字符串。注意:输入字符串s中可能会存在前导空格、尾......
  • 力扣第五十题——Pow(x,n)
    内容介绍实现 pow(x, n) ,即计算 x 的整数 n 次幂函数(即,xn )。示例1:输入:x=2.00000,n=10输出:1024.00000示例2:输入:x=2.10000,n=3输出:9.26100示例3:输入:x=2.00000,n=-2输出:0.25000解释:2-2=1/22=1/4=0.25提示:-100.0<x<100.0-2......
  • 《最新出炉》系列小成篇-Python+Playwright自动化测试-66 - 等待元素至指定状态(出现
    1.简介在我们日常工作中进行UI自动化测试时,保证测试的稳定性至关重要。其中一个关键方面是正确地定位和操作网页中的元素。在网页中,元素可能处于不同的状态,有些可能在页面加载完成之前不在DOM中,需要某些操作后才会出现,而其他元素可能一直存在于DOM中,但最初处于隐藏状态,需要通过操......
  • 力扣1.给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值
    1.给定一个整数数组nums和一个整数目标值target,请你在该数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。你可以按任意顺序返回答案。letnums=[1,2,4,5,3,2,4,6......
  • LeetCode150 逆波兰表达式求值
    前言题目:150.逆波兰表达式求值文档:代码随想录——逆波兰表达式求值编程语言:C++解题状态:成功解答!思路还是利用栈的思想,遍历到数字时,加入栈,遍历到运算符时,取出两个数进行运算,并将结果加入到栈中。代码classSolution{public:intevalRPN(vector<string>......
  • 算法力扣刷题记录 六十八【131.分割回文串】
    前言回溯章节第六篇。切割问题。记录六十八【131.分割回文串】。一、题目阅读给你一个字符串s,请你将s分割成一些子串,使每个子串都是回文串。回文串指字符串从前读和从后读一样。返回s所有可能的分割方案。示例1:输入:s="aab"输出:[["a","a","b"],["aa","b"]]......
  • 203. 移除链表元素 给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满
    在链表中,每个节点都有一个指向下一个节点的指针。删除一个节点的本质是将前一个节点的指针指向要删除节点的下一个节点,从而跳过要删除的节点。以下是详细解释为什么以及如何这样做:1.**链表的结构**:  一个链表节点包含两个部分:存储的数据和指向下一个节点的指针。  ``......
  • 力扣每日一题2024.8.5
    600.不含连续1的非负整数(困难)给定一个正整数n,请你统计在[0,n]范围的非负整数中,有多少个整数的二进制表示中不存在连续的1。示例1:输入:n=5输出:5解释:下面列出范围在[0,5]的非负整数与其对应的二进制表示:0:01:12:103:114:1005:101......
  • leetcode力扣第29题:两数相除
    这题看似简单,实则一点也不难(不是),实则还是比较困难。最简单的做法是直接用减法,不停循环计数,最后统计减多少次能成。如果被除数是2^31-1或差不多大小的数,而除数是1差不多大小的数,那循环减法要执行的次数太多,一定会超时。所以一定要有更好的思路(1)通过二分法查找可能的商(2)对于......
  • P2150 [NOI2015] 寿司晚宴
    思路:注意到对于每个数,其\(>19\)的质因数最多只有\(1\)个,称为大质数;对于\(\le19\)的质因数有\(8\)个,称为小质数。设第\(i\)个数的小质数集合为\(h_i\)。那么考虑对于所有数按照大质数从小到大排序,那么对于大质数相同的一段,只能放在两个集合中的一个。考虑状态压缩......