题目:移除元素
题目链接:(https://leetcode-cn.com/problems/remove-element/)
第一印象:
与昨天的移除相同元素的类似
(参见:https://blog.csdn.net/DZZ18803835618/article/details/104607900)
首先,将双指针思想拿来就用:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len = nums.size();
if(len == 0) return 0;
int i = 0;
for(int j = 0; j < len; j++)
{
if(nums[j] != val)
{
nums[i] = nums[j];
i++;
}
}
return i;
}
};
但是速度太慢:
二次尝试:
看了官方的解答,尝试了一下,果然速度翻了倍(可能是因为测试用例需要移除的元素不多缘故)
原理大概是这样子:每次只有在遇到要移除的元素时,用末位元素来覆盖这个元素,将数组长度减一,相比“第一印象”节省了大量复制不需要移除元素的时间,但是在需要大量移除元素的测试用例中,时间应当是差不多的。代码如下:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int n = nums.size();
int i = 0;
while(i < n)
{
if(nums[i] == val)
{
nums[i] = nums[n - 1];
n--;
}
else
{
i++;
}
}
return n;
}
};
在这里,我想特别说一下while的使用,可能是自身习惯的缘故,每次使用循环结构体时,总是习惯性的用for,for的使用可能更精巧,但是也要具体场景具体分析。
三次尝试:
至此,速度还算说得过去,无意中点开了最快用例的解法,发现可以用STL容器的erase(),找到之后直接将此元素消除:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
for(int i = 0;i < nums.size(); i++)
{
if(nums[i] == val)
{
nums.erase(nums.begin() + i);
i--;
}
}
return nums.size();
}
};
写完后,满怀信心的提交,结果:
这不科学啊,一样的代码,为什么我就只战胜了30%的人,怀着不服输的斗志,又重新提交,结果发现,每次都有质的飞跃啊~~
看来大家以后如果觉得自己的代码已经很精巧了,但是给出的时间不尽人意的话,可以多试几次(如果明知道很暴力就算了)
题外话:
以前自己不是很喜欢写代码,虽然现在也不是很喜欢,但终于认清了自己的位置。作为大三计算机科班现在觉悟已经相当晚了,以后每篇文章的最后都附上一句话吧,视心境而定,算对自己的激励,与君共勉。
永远都不早,永远都不晚