一、题目
1、题目地址
https://leetcode.com/problems/remove-element/description/
2、题目描述
Given an array and a value, remove all instances of that value in-place and return the new length.
Do not allocate extra space for another array, you must do this by modifying the input array in-place with O(1) extra memory.
The order of elements can be changed. It doesn’t matter what you leave beyond the new length.
Example:
Given nums = [3,2,2,3], val = 3,
Your function should return length = 2, with the first two elements of nums being 2.
二、解决方案
1、思想分析
既然题中明确说明只能使用 O(1) O ( 1 ) 的额外的内存,就说明想通过借助辅助数组来删除某个值的想法是不可行的,所以我们只能想办法在原vector上进行操作,看了下API文档,发现erase()这个函数可以做到将某一个或者某几个元素删除的效果,所以这里使用这个函数完成本题的代码。(其实这只是基础,只不过本菜鸟之前只用过pop,没用过erase(),代码敲的少啊,现在好好敲吧),本文主要有两种代码写法,因为在调试过程中都出现问题,所以记录一下。
2、程序代码(一)
代码如下,解释会写在注释上。
#include <iostream>
#include <vector>
using namespace std;
int removeElement(vector<int>& nums, int val) {
int count = nums.size(); //count表示删除某个值之后剩余的元素数目
vector<int>::iterator it = nums.begin();
if (*it == val) { //若有需要删除的元素
it = nums.erase(it); //应该将迭代器的值赋给it,否则it会找不到值,不知道从哪里开始继续执行
--count;
}
else {
++it; //若不需要删除,则继续往后执行
}
}
//测试输出的代码
/*
for (int j = 0; j < nums.size(); ++j) {
cout << nums[j] << " ";
}
cout << endl;
*/
return count;
}
int main()
{
vector<int> temp;
temp.push_back(1);
temp.push_back(3);
temp.push_back(0);
temp.push_back(2);
temp.push_back(3);
int replaced = 0;
cout << removeElement(temp, replaced) << endl;
return 0;
}
这里有个关于iterator返回值的坑需要特别注意(得某先生的帮助,非常感谢!):
下面是关于erase()的API文档内容:
即,在erase某一个元素之后,迭代器会自动定位到这个被删除元素的后一个元素,所以在上述程序中,我们直接将erase返回的结果赋给it迭代器,即能保证程序可以正常向下运行。(其实有很多代码中,是在erase某一个元素之后,仍然使用it = nums.begin(),即将程序从第一个元素开始重新运行,这样结果没有问题,但是对性能影响比较大)
3、运行结果(一)
113 / 113 test cases passed.
Status: Accepted
Runtime: 6 ms
4、程序代码(二)
代码如下,本代码没有使用iterator,直接使用数组下标进行定位:
#include <iostream>
#include <vector>
using namespace std;
int removeElement(vector<int>& nums, int val) {
int n = nums.size(), count = n; //count表示删除某个值之后剩余的元素数目
for (int i = 0; i < n; ++i) {
if (nums[i] == val) { //若元素需要删除
nums.erase(nums.begin() + i); //表示删除第i个元素(数组下标为i)
-- count;
-- i; //删除之后下标需要减1(因为无论怎么写,for循环中始终会执行++i,所以若这里不减1,erase某元素之后,for中i+1,会使得erase的后一个元素被忽略掉)
n = nums.size(); //这里再次求nums的原因是,erase之后,真实的nums数组元素数量变小,若不重新计算,则执行到nums[i]时会数组越界
}
}
//测试输出的代码
/*
for (int j = 0; j < nums.size(); ++j) {
cout << nums[j] << " ";
}
cout << endl;
*/
return count;
}
int main()
{
vector<int> temp;
temp.push_back(0);
temp.push_back(3);
temp.push_back(0);
temp.push_back(2);
temp.push_back(3);
int replaced = 0;
cout << removeElement(temp, replaced) << endl;
return 0;
}
这里容易出错的地方,一个是 - - i; 忘记,导致erase的后一个元素被忽略判断;另一个便是当erase之后,若不对数组长度重新计算,将导致新数组长度较小,而for循环中n不变,导致执行到nums[i]时,数组越界。
5、运行结果(二)
113 / 113 test cases passed.
Status: Accepted
Runtime: 5 ms