algorithm-base/animation-simulation/数组篇/leetcode27移除元素.md

142 lines
5.1 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

> 如果阅读时发现错误或者动画不可以显示的问题可以添加我微信好友 **[tan45du_one](https://raw.githubusercontent.com/tan45du/tan45du.github.io/master/个人微信.15egrcgqd94w.jpg)** ,备注 github + 题目 + 问题 向我反馈
>
> 感谢支持该仓库会一直维护希望对各位有一丢丢帮助
>
> 另外希望手机阅读的同学可以来我的 <u>[**公众号袁厨的算法小屋**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u> 两个平台同步,想要和题友一起刷题,互相监督的同学,可以在我的小屋点击<u>[**刷题小队**](https://raw.githubusercontent.com/tan45du/test/master/微信图片_20210320152235.2pthdebvh1c0.png)</u>进入。
#### [27. 移除元素](https://leetcode-cn.com/problems/remove-element/)
**题目描述**
> 给你一个数组 nums 和一个值 val你需要 原地 移除所有数值等于 val 的元素并返回移除后数组的新长度
>
> 不要使用额外的数组空间你必须仅使用 O(1) 额外空间并 原地 修改输入数组
>
> 元素的顺序可以改变你不需要考虑数组中超出新长度后面的元素
**示例 1:**
> 给定 nums = [3,2,2,3], val = 3,
>
> 函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2
>
> 你不需要考虑数组中超出新长度后面的元素
**示例 2:**
> 给定 nums = [0,1,2,2,3,0,4,2], val = 2,
>
> 函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4
>
> 注意这五个元素可为任意顺序
>
> 你不需要考虑数组中超出新长度后面的元素
**暴力法**
**解析**
该题目也算是简单题目适合新手来做然后大家也不要看不起暴力解法我们可以先写出暴力解法然后再思考其他方法这对于我们的编码能力有很大的帮助我们来解析一下这个题目的做题思路他的含义就是让我们删除掉数组中的元素然后将数组后面的元素跟上来最后返回删除掉元素的数组长度即可比如数组长度为 10里面有2个目标值我们最后返回的长度为 8但是返回的 8 个元素需要排在数组的最前面那么暴力解法的话则就需要两个 for 循环一个用来找到删除另一个用来更新数组
![移除数组元素暴力法](https://cdn.jsdelivr.net/gh/tan45du/github.io.phonto2@master/myphoto/移除数组元素.lhuefelqd5o.png)
总体思路就是这样的后面的会不断往前覆盖暴力解法也是不超时的实现也不算太简单主要需要注意两个地方
1需要先定义变量len获取数组长度因为后面我们的返回的数组长度是改变的所以不可以用 nums.length 作为上界
2我们每找到一个需要删除的值的时候需要i--防止出现多个需要删除的值在一起的情况然后漏删
**题目代码**
```java
class Solution {
public int removeElement(int[] nums, int val) {
//获取数组长度
int len = nums.length;
if (len == 0) {
return 0;
}
int i = 0;
for (i = 0; i < len; ++i) {
//发现符合条件的情况
if (nums[i] == val) {
//前移一位
for (int j = i; j < len-1; ++j) {
nums[j] = nums[j+1];
}
i--;
len--;
}
}
return i;
}
}
```
**双指针**
快慢指针的做法比较有趣只需要一个 for 循环即可解决时间复杂度为 O(n) ,总体思路就是有两个指针前面一个后面一个前面的用于搜索需要删除的值当遇到需要删除的值时前指针直接跳过后面的指针不动当遇到正常值时两个指针都进行移动并修改慢指针的值最后只需输出慢指针的索引即可
**动图解析:**
![](https://img-blog.csdnimg.cn/20210317194638700.gif#pic_center)
**题目代码**
Java Code:
```java
class Solution {
public int removeElement(int[] nums, int val) {
int len = nums.length;
if (len == 0) {
return 0;
}
int i = 0;
for (int j = 0; j < len; ++j) {
//如果等于目标值,则删除
if (nums[j] == val) {
continue;
}
// 不等于目标值时则赋值给num[i],i++
nums[i++] = nums[j];
}
return i;
}
}
```
Python3 Code:
```python
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
i = 0
for j in range(len(nums)):
if nums[j] != val:
nums[i] = nums[j]
i += 1
return i
```
C++ Code:
```cpp
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int n = nums.size();
if(!n) return 0;
int i = 0;
for(int j = 0; j < n; ++j){
if(nums[j] == val) continue;
nums[i++] = nums[j];
}
return i;
}
};
```