所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。
题目
一、暴力穷解法
思路分析:暴力破解的思路很简单,就是利用for循环挨个遍历,当找到一个val值时,就把数组中所有的值往前面挪一位,然后数组大小减一(初始大小和目标数组大小相等),同时索引减一。
程序如下:
// 暴力穷解法
int removeElement2(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];
}
size--;
i--;
}
}
return size;
}
复杂度分析:
- 时间复杂度: O ( n 2 ) O(n^2) O(n2),主要来自两个for循环,因此是 O ( n 2 ) O(n^2) O(n2)的复杂度。
- 空间复杂度: O ( 1 ) O(1) O(1)。
算法对比:
二、双指针法
思路分析:双指针的特点是具有一个快指针和一个慢指针。双指针的工作原理可以分成两个部分:快指针在每次遍历时都++,慢指针只有在nums[fastIndex] !=val的时候++,进入if语句时,慢指针指向的值就是val,快指针指向的值不是val。等于说,程序实质上是把慢指针指向的值替换快指针指向的值,从而实现删除操作。
程序如下:
// 双指针法
int removeElement(vector<int>& nums, int val) {
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
if (nums[fastIndex] != val) {
nums[slowIndex++] = nums[fastIndex];
}
}
return slowIndex;
}
复杂度分析:
- 时间复杂度: O ( n ) O(n) O(n),这个算法需要遍历整个数组。
- 空间复杂度: O ( 1 ) O(1) O(1),固定内存。
算法对比:
完整代码
// 27.LeetCode移除元素
# include <iostream>
# include <vector>
using namespace std;
class Solution {
public:
// 双指针法
int removeElement(vector<int>& nums, int val) {
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
if (nums[fastIndex] != val) {
nums[slowIndex++] = nums[fastIndex];
}
}
return slowIndex;
}
};
void my_print(vector<int> v, string str) {
cout << str << endl;
for (vector<int>::iterator it = v.begin(); it < v.end(); it++) {
cout << *it << ' ';
}
cout << endl;
}
int main()
{
int val = 3;
int arr[] = {
3,2,2,3 };
vector<int> nums;
Solution s1;
for (int i = 0; i < sizeof(arr) / sizeof(int); i++){
nums.push_back(arr[i]);
}
my_print(nums, "目标数组:");
int size = s1.removeElement(nums, val);
my_print(nums, "删除元素后的数组:");
cout << size << endl;
system("pause");
return 0;
}
end