题目:
给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
这道题与上一篇文章中的题目真没多大区别,感觉基本就是一个类型的。随便改了一下就做出来了:
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int removeDuplicates(vector<int>& nums,int val) {
if (nums.empty()) {
return 0;
}
int index = 0;
for (int j = 0; j < nums.size(); j++) {
if (nums[j] != val) {
nums[index] = nums[j];
index++;
}
}
std::cout << "返回删除数组重复项后数组的长度:" << '\n';
std::cout << index << '\n';
return index ;
}
};
int main() {
Solution S;
vector<int> nums = { 1,2,3,3,3,3,4,4,3,5,4,5 };
int temp=3;
int tem = S.removeDuplicates(nums,temp);
std::cout << "新数组:" << '\n';
for (int i = 0; i < tem; i++) {
std::cout << nums[i] << ' ';
}
return 0;
}
仔细看一下这个代码与上一篇博客中的代码其实就差了个for循环在里面。同样使用的也是双指针的结构,一个指针循环遍历,另一个指针用于赋值。当第一个指针所指向的值不等于目标值时,将其赋值给第二个指针所指向的位置,同时第二个指针自加一。当第一个指针所指向的值等于目标值时,第二个指针不动,第一个指针自加一。这样循环遍历一遍就可以把所有需要去除的值都剔除掉了。
思路二:
leetcode上还给出了另外一种优化方法:
如果要移除的元素恰好在数组的开头,例如序列 [1,2,3,4,5],当 val 为 11 时,我们需要把每一个元素都左移一位。注意到题目中说:「元素的顺序可以改变」。实际上我们可以直接将最后一个元素 5 移动到序列开头,取代元素 1,得到序列 [5,2,3,4],同样满足题目要求。这个优化在序列中 val 元素的数量较少时非常有效。
实现方面,我们依然使用双指针,两个指针初始时分别位于数组的首尾,向中间移动遍历该序列。
如果左指针left 指向的元素等于val,此时将右指针right 指向的元素复制到左指针 left 的位置,然后右指针 right 左移一位。如果赋值过来的元素恰好也等于val,可以继续把右指针right 指向的元素的值赋值过来(左指针 left 指向的等于val 的元素的位置继续被覆盖),直到左指针指向的元素的值不等于val 为止。
当左指针left 和右指针right 重合的时候,左右指针遍历完数组中所有的元素。
这样的方法两个指针在最坏的情况下合起来只遍历了数组一次。与方法一不同的是,方法二避免了需要保留的元素的重复赋值操作。
不得不说思路还是挺巧妙的
两种算法都是能够实现的,代码如下:
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
int removeDuplicates(vector<int>& nums,int val) {
if (nums.empty()) {
return 0;
}
int index = 0;
for (int j = 0; j < nums.size(); j++) {
if (nums[j] != val) {
nums[index] = nums[j];
index++;
}
}
std::cout << "返回删除数字3后数组的长度:" << '\n';
std::cout << index << '\n';
return index ;
}
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++;
}
}
std::cout << "返回删除数字4后数组的长度:" << '\n';
std::cout << left << '\n';
return left;
}
};
int main() {
Solution S;
vector<int> nums = { 1,2,3,3,3,3,4,4,3,5,4,5 };
vector<int> nums2 = { 1,2,3,3,3,3,4,4,3,5,4,5 };
std::cout << "原数组:" << '\n';
for (int i = 0; i < nums.size(); i++) {
std::cout << nums[i] << ' ';
}
std::cout << '\n';
int temp=3;
int temp2 = 4;
int tem = S.removeDuplicates(nums,temp);
std::cout << "新数组:" << '\n';
for (int i = 0; i < tem; i++) {
std::cout << nums[i] << ' ';
}
std::cout << '\n';
int tem2 = S.removeElement(nums2, temp2);
std::cout << "新数组2:" << '\n';
for (int i = 0; i < tem2; i++) {
std::cout << nums2[i] << ' ';
}
return 0;
}