????????对于给定的数组nums,要求移除其中值为val的元素,且不使用额外的数组空间,返回移除后数组的新长度。
????????数组nums中元素的顺序可以改变。
????????双指针法是解算法题常用且非常有效的一种方法。
????????设置双指针left和right,指针right从左向右遍历数组元素,指针left更新数组nums中的元素。函数返回left。
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int n = nums.size();
int left = 0;
for (int right = 0; right < n; right++) {
if (nums[right] != val) {
nums[left] = nums[right];
left++;
}
}
return left;
}
};
int main() {
int x[] = { 3,2,2,3 };
int val = 3;
vector<int> nums;
for (int i = 0; i < 4; i++)
{
nums.push_back(x[i]);
}
Solution S;
int ans = S.removeElement(nums, val);
cout << ans << endl;
return 0;
}
????????前移法是与双指针法非常相似的一种方法。不同的是,双指针法的left指针用于放置元素,前移法的变量k用于统计要删除的元素个数并将保留的元素前移k个位置。
????????指针right遍历数组nums的元素,变量k统计要删除的元素的个数,同时将指针right扫描到的要保留的元素前移k个位置。
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int n = nums.size();
int k = 0; //k累计当前等于val的元素个数
for (int right = 0; right < n; right++) {
if (nums[right] == val) {
k++;
}
else {
nums[right - k] = nums[right];
}
}
return n - k;
}
};
int main() {
int x[] = { 3,2,2,3 };
int val = 3;
vector<int> nums;
for (int i = 0; i < 4; i++)
{
nums.push_back(x[i]);
}
Solution S;
int ans = S.removeElement(nums, val);
cout << ans << endl;
return 0;
}
????????对于这一题,可以将双指针法进行优化。
????????本题数组nums中元素的顺序可以改变,所以可以使用while循环,通过双指针left和right,分别从左、从右扫描数组元素。指针left不仅遍历数组元素,也放置新元素。
????????当指针left和指针right重合时,结束循环。
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int left = 0, right = nums.size();
while (left < right) {
if (nums[left] == val) {
nums[left] = nums[right - 1];
right--;
}
else {
left++;
}
}
return left;
}
};
int main() {
int x[] = { 3,2,2,3 };
int val = 3;
vector<int> nums;
for (int i = 0; i < 4; i++)
{
nums.push_back(x[i]);
}
Solution S;
int ans = S.removeElement(nums, val);
cout << ans << endl;
return 0;
}