当前位置:网站首页>LeetCode 移除元素&移动零
LeetCode 移除元素&移动零
2022-07-28 11:49:00 【.DoubleBean.】
题目地址(27. 移除元素)
https://leetcode-cn.com/problems/remove-element/
题目描述
给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
说明:
为什么返回数值是整数,但输出的答案是数组呢?
请注意,输入数组是以「引用」方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。
你可以想象内部操作如下:
// nums 是以“引用”方式传递的。也就是说,不对实参作任何拷贝
int len = removeElement(nums, val);
// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中 该长度范围内 的所有元素。
for (int i = 0; i < len; i++) {
print(nums[i]);
}
示例 1:
输入:nums = [3,2,2,3], val = 3
输出:2, nums = [2,2]
解释:函数应该返回新的长度 2, 并且 nums 中的前两个元素均为 2。你不需要考虑数组中超出新长度后面的元素。例如,函数返回的新长度为 2 ,而 nums = [2,2,3,3] 或 nums = [2,2,0,0],也会被视作正确答案。
示例 2:
输入:nums = [0,1,2,2,3,0,4,2], val = 2
输出:5, nums = [0,1,4,0,3]
解释:函数应该返回新的长度 5, 并且 nums 中的前五个元素为 0, 1, 3, 0, 4。注意这五个元素可为任意顺序。你不需要考虑数组中超出新长度后面的元素。
提示:
0 <= nums.length <= 100
0 <= nums[i] <= 50
0 <= val <= 100
暴力解法:两层for循环
// 时间复杂度: O(N^2)
// 空间复杂度: O(1)
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len = nums.size();
for(int i=0; i<len; i++){
if(nums[i] == val){
//找到需要移除的元素,就将数组集体向前移动一位
for(int j=i+1; j<len; j++)
nums[j-1] = nums[j];
i--; //因为下标i以后的数值都向前移动了一位
len--; //此时数组的大小-1
}
}
return len;
}
};
申请一个额外的动态数组
申请一个额外的动态数组,遍历nums数组时,将不等于val的值拷贝到动态数组中
之后把动态数组内容拷贝回nums数组,返回nums.size()即可
// 时间复杂度: O(N)
// 空间复杂度: O(N)
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len = nums.size();
vector<int> data;
for(int i=0; i<len; i++){
if(nums[i] != val)
data.push_back(nums[i]);
}
nums.assign(data.begin(), data.end()); // nums = data;
return nums.size();
}
};
前两种方法虽然都能通过,但不符合题目的O(1)额外空间这一条件。
双指针法(快慢指针法)
[通过一个快指针和慢指针在一个for循环下实现两个for循环工作]
// 时间复杂度: O(N)
// 空间复杂度: O(1)
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowindex = 0, len = nums.size();
for(int quickindex=0;quickindex<len;quickindex++){
if(nums[quickindex] != val)
nums[slowindex++] = nums[quickindex];
}
return slowindex;
}
};
官方题解
当num=[4,1,2,3,5],val=4,似乎没有必要将 [1,2,3,5] 这几个元素左移一步,因为问题描述中提到元素的顺序可以更改,那么将4与数组末尾的5互换,然后len-=1,就相当于把4删除了
当我们遇到 nums[i] = val 时,我们可以将当前元素与最后一个元素进行交换,并释放最>后一个元素。这实际上使数组的大小减少了 1
请注意,被交换的最后一个元素可能是您想要移除的值。但是不要担心,在下一次迭代中,我们仍然会检查这个元素。
// 时间复杂度: O(N)
// 空间复杂度: O(1)
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len = nums.size(), i = 0;
while(i<len){
if(nums[i] == val){
nums[i] = nums[len-1];
len--;
}
else
i++;
}
return len;
}
};
题目地址(283. 移动零)
https://leetcode-cn.com/problems/move-zeroes/
题目描述
给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。
示例:
输入: [0,1,0,3,12]
输出: [1,3,12,0,0]
说明:
必须在原数组上操作,不能拷贝额外的数组。
尽量减少操作次数。
两次遍历
//时间复杂度:O(N)
//空间复杂度:O(1)
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int slowindex = 0, len = nums.size();
//第一次遍历时,将非0元素统统都赋给nums
for(int quickindex=0; quickindex<len; quickindex++){
if(nums[quickindex] != 0)
nums[slowindex++] = nums[quickindex];
}
//非0统计完,剩下都是0了,把末尾的元素全都赋给0即可
while(slowindex<len)
nums[slowindex++] = 0;
}
};
提示:与 移除元素 的快慢指针题解进行比较
一次遍历
参考快排的思想(这思路实在是太妙了),将0作为基准数,把不等于0的数 nums[i] != 0 放在基准数左边,等于0的 nums[i] == 0 放在其右边
//时间复杂度:O(N)
//空间复杂度:O(1)
class Solution {
public:
void moveZeroes(vector<int>& nums) {
//两个指针i和j
int j = 0, len = nums.size();
for(int i=0; i<len; i++){
if(nums[i] != 0){
int temp = nums[i];
nums[i] = nums[j];
nums[j++] = temp;
}
}
}
};
优化下代码
//时间复杂度:O(N)
//空间复杂度:O(1)
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int j = 0, len = nums.size();
for(int i=0; i<len; i++){
if(nums[i] != 0){
if(i>j){
nums[j] = nums[i];
nums[i] = 0;
}
j++; //这一步不能漏掉
}
}
}
};
当nums[i] != 0时,若i==j,表明数组开头的前面这一堆数都是非零的,无需进行任何操作,若 i > j 时,只需要把 nums[i] 的值赋值给 nums[j],并把原位置的值赋值为0
参考的大佬题解:
边栏推荐
- Use json.stringify() to format data
- Pits encountered in MSP430 development (to be continued)
- Communication example between upper computer and Mitsubishi fn2x
- 试用copilot过程中问题解决
- Knowledge points of MySQL (13)
- VS code更新后不在原来位置
- 用C语言开发NES游戏(CC65)04、完整的背景
- Open source huizhichuang future | 2022 open atom global open source summit openatom openeuler sub forum was successfully held
- Tik tok "founder" Yang Luyu, farewell byte?
- Library automatic reservation script
猜你喜欢

Using Arduino to develop esp8266 to build a development environment

设计一个线程池

Analysys analysis: focus on users, improve the user experience of mobile banking, and help the growth of user value

非标自动化设备企业如何借助ERP系统,做好产品质量管理?

Knowledge points of MySQL (13)

Aopmai biological has passed the registration: the half year revenue is 147million, and Guoshou Chengda and Dachen are shareholders

新东方单季营收5.24亿美元同比降56.8% 学习中心减少925间

奥浦迈生物通过注册:半年营收1.47亿 国寿成达与达晨是股东

AsiaInfo technology released antdb7.0, a "Telecom grade" core transaction database, to help government and enterprises "trust" to create the future!

Foam exploded three times, why did Luo Yonghao put all his eggs in one basket to do ar?
随机推荐
Arduino Pro Mini atmega328p connect and light the first LED (at the same time, record the problem of burning failure stk500_recv)
SuperMap itablet license module division
Hc-05 Bluetooth module debugging slave mode and master mode experience
Holes in [apue] files
新东方单季营收5.24亿美元同比降56.8% 学习中心减少925间
AI制药的数据之困,分子建模能解吗?
Open source huizhichuang future | 2022 open atom global open source summit openatom openeuler sub forum was successfully held
试用copilot过程中问题解决
C for循环内定义int i变量出现的重定义问题
用C语言开发NES游戏(CC65)03、VRAM缓冲区
Communication example between upper computer and Mitsubishi fn2x
VS code更新后不在原来位置
First in the country! The two standards of "data product registration" formulated by insight technology and Shandong data were officially released
Multi Chain and multi currency wallet system development cross chain technology
Custom paging tag 02 of JSP custom tag
VS1003 debugging routine
Unity加载Glb模型
GMT installation and use
04 pyechars 地理图表(示例代码+效果图)
用C语言开发NES游戏(CC65)05、调色板