【蓝桥Java每日一练】————4.移除元素

简介: 今天给大家带来一道基础的双指针题目移除元素

🍋1.移除元素


给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。


不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。


元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。


题目链接:移除元素https://leetcode-cn.com/problems/remove-element/        


            题目解析:首先大家要清楚这里所谓的移除元素,并不是真的移除,我们数组的内存都是连续存储的,是不能单独删除数组中某个元素的,只能进行覆盖。这里之所以要返回新的新数组长度,是它对原数组只遍历到该长度。所以我们的目的就是让值为val的元素全部被后面的元素覆盖掉。


方法1:暴力遍历


           因为目的是要把val全部放到后面,我们可以通过两层for循环,第一层对数组进行遍历,当找到值为val的元素后,我们让val后面的元素全部向前移动一格,这样就将val覆盖掉了。很多人肯定很奇怪,那你这样val不是就没有了?可以答案并不关心你数组尾部的元素是多少,它只会遍历你给的返回值的长度,当然你也可以让val不断和后面元素交换,把它放到后面去,不过那样便是多此一举了。


          时间复杂度O(n^2):n为数组的长度,两层for循环,最坏的情况下会对数组完全遍历两次


          空间复杂度O(1)


class Solution {
    public int removeElement(int[] nums, int val) {
        int n=nums.length;
        //遍历数组
        for(int i=0;i<n;i++){
            //找到了val
            if(nums[i]==val){
                //把val后面的元素全部向前移动一格
                for(int j=i+1;j<n;j++){                
                   nums[j-1]=nums[j];
                }
                //因为后面的元素都向前移动了一格,i也得往左移动一格(仔细想想)        
                i--;
                //删除了一个val,长度当然要减1,这也是我们最后需要返回的答案。
                n--;
            }
        }
        return n;
    }
}


方法2:快慢双指针


            我们定义一个慢指针slowIndex和一个fastIndex,在一个for循环中可以同时完成上面暴力做法的工作。首先两个指针都从数组开始,然后for循环让快指针进行移动,每次移动后判断,快指针的值是否为val,如果不是则将快指针的值覆盖掉慢指针,然后慢指针移动一格。很多人肯定看不懂这个操作的作用,我们的目的既然是主要除了val的其他元素,那我们是不是将除了val的其他元素放到数组前面即可,慢指针的意义代表的是待插入的下标,快指针就是去寻找不为val的元素,理解两个指针的意义再回去看操作大家伙就能明白了。


          时间复杂度O(n):n为数组的长度,只遍历了数组一次        


          空间复杂度O(1)


class Solution {
    public int removeElement(int[] nums, int val) {
        //快慢指针 
        int slowIndex;
        for (int fastIndex = 0; fastIndex < nums.length; fastIndex++) {
            //不等于val才是我们需要的元素
            if (nums[fastIndex] != val) {
                //把它放到慢指针的位置
                nums[slowIndex] = nums[fastIndex];
                //慢指针移动一格
                slowIndex++;
            }
        }
        //慢指针最后指向的下标就是我们往前放入元素的个数,也就是我们的答案
        return slowIndex;
    }
}

           将朴素做法和双指针做法同时写出来和解析,可以更加让我们感受到双指针的魔力所在,帮助我们更好理解。


相关文章
|
28天前
|
存储 算法 Java
Arraylist 在 Java 中能容纳多少个元素?
【8月更文挑战第23天】
51 0
|
28天前
|
存储 Java
|
10天前
|
Java 编译器 测试技术
|
23天前
|
存储 Java
Java中ArrayList 元素的排序
本文提供了Java中根据`ArrayList`元素的某个属性进行排序的示例代码,包括实现`Comparable`接口和重载`compareTo`方法,然后使用`Collections.sort`方法进行排序。
|
28天前
|
存储 安全 Java
|
28天前
|
Java
|
28天前
|
存储 Java API
|
6天前
|
存储 缓存 安全
【Java面试题汇总】多线程、JUC、锁篇(2023版)
线程和进程的区别、CAS的ABA问题、AQS、哪些地方使用了CAS、怎么保证线程安全、线程同步方式、synchronized的用法及原理、Lock、volatile、线程的六个状态、ThreadLocal、线程通信方式、创建方式、两种创建线程池的方法、线程池设置合适的线程数、线程安全的集合?ConcurrentHashMap、JUC
【Java面试题汇总】多线程、JUC、锁篇(2023版)
|
17天前
|
监控 Java 调度
【Java学习】多线程&JUC万字超详解
本文详细介绍了多线程的概念和三种实现方式,还有一些常见的成员方法,CPU的调动方式,多线程的生命周期,还有线程安全问题,锁和死锁的概念,以及等待唤醒机制,阻塞队列,多线程的六种状态,线程池等
79 6
【Java学习】多线程&JUC万字超详解
|
3天前
|
Java
深入理解Java中的多线程编程
本文将探讨Java多线程编程的核心概念和技术,包括线程的创建与管理、同步机制以及并发工具类的应用。我们将通过实例分析,帮助读者更好地理解和应用Java多线程编程,提高程序的性能和响应能力。
15 4