一、暴力法,for循环遍历寻找需删除的元素,然后for循环用后面的元素向前覆盖
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int size = nums.size();
for (int i = 0; i < size; i++) {
if (nums[i] == val) { // 发现需要移除的元素,就将数组集体向前移动一位
for (int j = i + 1; j < size; j++) {
nums[j - 1] = nums[j];
}
i--; // 因为下标i以后的数值都向前移动了一位,所以i也向前移动一位
size--; // 此时数组的大小-1
}
}
return size;
}
};
时间复杂度:O(n^2)
空间复杂度: O(1)
二、双指针法
快慢双指针法,快指针指向新数组需要的元素,慢指针指向新数组元素的位置
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
//快慢双指针法,快指针指向新数组需要的元素,慢指针指向新数组元素的位置
int slow=0;
for(int quick=0;quick<nums.size();quick++)
{
//若快指针指向的是非删除元素,则更新数组元素
if(nums[quick]!=val)
{
nums[slow]=nums[quick];
slow++;
}
}
//slow所在位置即新数组的大小
return slow;
}
};
时间复杂度:O(n)
空间复杂度: O(1)
题2:[leetcode 26]
给你一个 非严格递增排列 的数组
nums
,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回nums
中唯一元素的个数。考虑
nums
的唯一元素的数量为k
,你需要做以下事情确保你的题解可以被通过:
- 更改数组
nums
,使nums
的前k
个元素包含唯一元素,并按照它们最初在nums
中出现的顺序排列。nums
的其余元素与nums
的大小不重要。- 返回
k
。
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int slow=0,n=nums.size();
for(int quick=1;quick<n;quick++)
{
if(nums[quick]!=nums[slow]){
nums[++slow]=nums[quick];
}
}
return slow+1;
}
};
时间复杂度:O(n)
空间复杂度:O(1)
题3:[leetcode 28]
给定一个数组
nums
,编写一个函数将所有0
移动到数组的末尾,同时保持非零元素的相对顺序。请注意 ,必须在不复制数组的情况下原地对数组进行操作。
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int n=nums.size();
int slow=0;
for(int quick=0;quick<n;quick++)
{
if(nums[quick])
{
int temp=nums[slow];
nums[slow]=nums[quick];
nums[quick]=temp;
slow++;
}
}
}
};
时间复杂度:O(n)
空间复杂度:O(1)
4.[leetcode 844]
给定
s
和t
两个字符串,当它们分别被输入到空白的文本编辑器后,如果两者相等,返回true
。#
代表退格字符。注意:如果对空文本输入退格字符,文本继续为空。
解法一:
class Solution {
public:
bool backspaceCompare(string s, string t) {
//双指针法
//正序遍历很难知道当前字符是否被删除,所以采用逆序遍历
int i=s.length()-1,j=t.length()-1;
int skipS=0,skipT=0; //跳过字符数
while(i>=0||j>=0)
{
//筛选有效字符
while(i>=0)
{
//遇到#号
if(s[i]=='#'){
skipS++;
i--;
}
else if(skipS>0) {
skipS--;
i--;
}
else{
break;
}
}
while(j>=0)
{
//遇到#号
if(t[j]=='#'){
skipT++;
j--;
}
else if(skipT>0) {
skipT--;
j--;
}
else{
break;
}
}
//有效字符比较,可能出现情况:1.匹配,继续遍历 2.其中一个已遍历完成,而另一个还没遍历完成,则不匹配 3.两个都已遍历完成,匹配 4.两个都没遍历完成,但不相等,不匹配
if(i>=0&&j>=0){
if(s[i]!=t[j]) return false; //4
i--;j--; //1(->2/3)
}
else{
if(i<0&&j<0) return true; //3
else return false;//2
}
}
return true;//(1)
}
};
解法二[更加推荐]:先分别对s、t进行修改,把有效字符放到字符串尾部,并计算s、t有效字符数。在进行判断时,先比较有效长度,再比较具体字符,更易理解!
class Solution {
public:
bool backspaceCompare(string s, string t) {
//双指针法
int si=s.length()-1,skipS=0,cntS=0;
int ti=t.length()-1,skipT=0,cntT=0;
for(int sj=s.length()-1;sj>=0;sj--)
{
if(s[sj]=='#') skipS++;
else if(skipS>0) skipS--;
else {
cntS++;
s[si]=s[sj];
si--;
}
}
for(int tj=t.length()-1;tj>=0;tj--)
{
if(t[tj]=='#') skipT++;
else if(skipT>0) skipT--;
else {
cntT++;
t[ti]=t[tj];
ti--;
}
}
if(cntT!=cntS) return false;
else if(cntT==0) return true;
else{
int i=s.length()-1,j=t.length()-1;
for(int k=0;k<cntT;k++)
{
if(s[i--]!=t[j--]) return false;
}
return true;
}
}
};
时间复杂度:O(m+n)
空间复杂度:O(1)