【蓝桥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;
    }
}

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


相关文章
|
30天前
|
存储 Java
深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。
【10月更文挑战第16天】本文深入探讨了Java集合框架中的HashSet和TreeSet,解析了两者在元素存储上的无序与有序特性。HashSet基于哈希表实现,添加元素时根据哈希值分布,遍历时顺序不可预测;而TreeSet利用红黑树结构,按自然顺序或自定义顺序存储元素,确保遍历时有序输出。文章还提供了示例代码,帮助读者更好地理解这两种集合类型的使用场景和内部机制。
38 3
|
30天前
|
Java
在Java的世界里,Set只接纳独一无二的元素。
【10月更文挑战第16天】在Java的世界里,Set只接纳独一无二的元素。本文通过拟人化的手法,讲述了重复元素从初次尝试加入Set被拒绝,到经历挣扎、反思,最终通过改变自己,成为独特个体并被Set接纳的全过程。示例代码展示了这一过程的技术实现。
24 1
|
7天前
|
Java
那些与Java Set擦肩而过的重复元素,都经历了什么?
在Java的世界里,Set如同一位浪漫而坚定的恋人,只对独一无二的元素情有独钟。重复元素虽屡遭拒绝,但通过反思和成长,最终变得独特,赢得了Set的认可。示例代码展示了这一过程,揭示了成长与独特性的浪漫故事。
15 4
|
14天前
|
存储 Java
判断一个元素是否在 Java 中的 Set 集合中
【10月更文挑战第30天】使用`contains()`方法可以方便快捷地判断一个元素是否在Java中的`Set`集合中,但对于自定义对象,需要注意重写`equals()`方法以确保正确的判断结果,同时根据具体的性能需求选择合适的`Set`实现类。
|
13天前
|
存储 算法 Java
为什么Java Set如此“挑剔”,连重复元素都容不下?
在Java的集合框架中,Set是一个独特的接口,它严格要求元素不重复,适用于需要唯一性约束的场景。Set通过内部数据结构(如哈希表或红黑树)和算法(如哈希值和equals()方法)实现这一特性,自动过滤重复元素,简化处理逻辑。示例代码展示了Set如何自动忽略重复元素。
21 1
|
30天前
|
存储 Java 数据处理
Set 是 Java 集合框架中的一个接口,不包含重复元素且不保证元素顺序。
【10月更文挑战第16天】Java Set:无序之美,不重复之魅!Set 是 Java 集合框架中的一个接口,不包含重复元素且不保证元素顺序。通过 hashCode() 和 equals() 方法实现唯一性,适用于需要唯一性约束的数据处理。示例代码展示了如何使用 HashSet 添加和遍历元素,体现了 Set 的高效性和简洁性。
28 4
|
30天前
|
Java 开发者
在Java集合世界中,Set以其独特的特性脱颖而出,专门应对重复元素
在Java集合世界中,Set以其独特的特性脱颖而出,专门应对重复元素。通过哈希表和红黑树两种模式,Set能够高效地识别并拒绝重复元素的入侵,确保集合的纯净。无论是HashSet还是TreeSet,都能在不同的场景下发挥出色的表现,成为开发者手中的利器。
26 2
|
11天前
|
安全 Java 测试技术
Java并行流陷阱:为什么指定线程池可能是个坏主意
本文探讨了Java并行流的使用陷阱,尤其是指定线程池的问题。文章分析了并行流的设计思想,指出了指定线程池的弊端,并提供了使用CompletableFuture等替代方案。同时,介绍了Parallel Collector库在处理阻塞任务时的优势和特点。
|
7天前
|
安全 Java 开发者
深入解读JAVA多线程:wait()、notify()、notifyAll()的奥秘
在Java多线程编程中,`wait()`、`notify()`和`notifyAll()`方法是实现线程间通信和同步的关键机制。这些方法定义在`java.lang.Object`类中,每个Java对象都可以作为线程间通信的媒介。本文将详细解析这三个方法的使用方法和最佳实践,帮助开发者更高效地进行多线程编程。 示例代码展示了如何在同步方法中使用这些方法,确保线程安全和高效的通信。
28 9
|
10天前
|
存储 安全 Java
Java多线程编程的艺术:从基础到实践####
本文深入探讨了Java多线程编程的核心概念、应用场景及其实现方式,旨在帮助开发者理解并掌握多线程编程的基本技能。文章首先概述了多线程的重要性和常见挑战,随后详细介绍了Java中创建和管理线程的两种主要方式:继承Thread类与实现Runnable接口。通过实例代码,本文展示了如何正确启动、运行及同步线程,以及如何处理线程间的通信与协作问题。最后,文章总结了多线程编程的最佳实践,为读者在实际项目中应用多线程技术提供了宝贵的参考。 ####