leetcode刷题记录——移除元素
——参考代码随想录和力扣顺序刷题(https://programmercarl.com/)
本质:移动元素;双指针(快慢指针)(左右指针);
文章目录
27. 移除元素
26. 删除有序数组中的重复项
283. 移动零
844. 比较含退格的字符串
977.有序数组的平方
27. 移除元素(简单)
给你一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1) 额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
思路1:
- 将等于val的值移到数组最后方,然后pop_back;
代码1:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
for(int i = 0;i<nums.size();i++) {
if(nums[i] == val) {
swap(nums[i],nums[nums.size()-1]);
nums.pop_back();
i--;
}
}
return nums.size();
}
};
思路2:双指针(齐头并进,快慢之分)
- 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。
- 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
- 慢指针:指向更新新数组下标的位置
- 当nums[fastIndex]和val相等,则快指针多走一步,当不相等时,快指针指向的值,覆盖慢指针指向的值。
// 时间复杂度:O(n)
// 空间复杂度:O(1)
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
if (val != nums[fastIndex]) {
nums[slowIndex++] = nums[fastIndex];
}
}
return slowIndex;
}
};
思路3:
- 双指针(一头一尾,中间靠拢)
- 一个指针从前一个从后开始遍历,其中(任意)一个指针=val就被另一端!=val的值覆盖。
/**
* 相向双指针方法,基于元素顺序可以改变的题目描述改变了元素相对位置,确保了移动最少元素
* 时间复杂度:O(n)
* 空间复杂度:O(1)
*/
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int leftIndex = 0;
int rightIndex = nums.size() - 1;
while (leftIndex <= rightIndex) {
// 找左边等于val的元素
while (leftIndex <= rightIndex && nums[leftIndex] != val){
++leftIndex;
}
// 找右边不等于val的元素
while (leftIndex <= rightIndex && nums[rightIndex] == val) {
-- rightIndex;
}
// 将右边不等于val的元素覆盖左边等于val的元素
if (leftIndex < rightIndex) {
nums[leftIndex++] = nums[rightIndex--];
}
}
return leftIndex; // leftIndex一定指向了最终数组末尾的下一个元素
}
};
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
26. 删除有序数组中的重复项(简单)
思路:
- 双指针,快慢指针,一开始快慢指针指向同一个值,快指针每次循环+1,慢指针只有在nums[slowIndex] != nums[fastIndex]才会+1,并且将nums[fastIndex]的值覆盖到nums[slowIndex]上(因为当不相等时,slowIndex先+1,所以保证不会覆盖掉唯一的数字);
- 如果相等,
q
后移 1 位
如果不相等,将q
位置的元素复制到p+1
位置上,p
后移一位,q
后移 1 位
重复上述过程,直到q
等于数组长度。 - 因为返回数组长度,所以返回slowIndex + 1;
代码:
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int slowIndex = 0;
for (int fastIndex = 0; fastIndex < nums.size(); fastIndex++) {
if (nums[slowIndex] != nums[fastIndex]) {
slowIndex++;
nums[slowIndex] = nums[fastIndex];
}
}
return slowIndex + 1;
}
};
283. 移动零(简单)
将0移到最后的位置;
思路:
- 双指针,不等于0和0交换,若等于0,slowIndex不移动,保持slowIndex始终指向0;
代码:
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int slowIndex = 0;
for(int fastIndex = 0;fastIndex < nums.size();fastIndex++) {
if(nums[fastIndex] != 0 ){
swap(nums[slowIndex],nums[fastIndex]);
slowIndex++;
}
}
return;
}
};
844. 比较含退格的字符串(简单)
思路:
- 使用栈思想,如果当前字符不是 ‘#’ 则加入,如果是,则弹出;(string可以当栈使用);
代码:
class Solution {
public:
bool backspaceCompare(string s, string t) {
string S,T;
for(int i=0;i<s.length();i++) {
if(s[i] != '#') {
S += s[i];
}
else {
if(!S.empty())
S.pop_back();
}
}
for(int i=0;i<t.length();i++) {
if(t[i] != '#') {
T += t[i];
}
else {
if(!T.empty())
T.pop_back();
}
}
if(T == S) return true;
else return false;
}
};
977. 有序数组的平方(简单)
思路1:
- 将数组平方后排序。
思路2:
- 双指针(两边靠近),新开一个数组,常识可得,两边的平方更大,则一个left指针在0,right指针在size-1的位置向中间靠近,两个比较,谁大则谁逆序进入ans数组;
- 需要一个k来进行计数,还需要新开一个数组,临界条件是left <= right(要将最后一个数字(最小的)填进数组;
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
int right = nums.size() - 1;
int k = nums.size() - 1;
int left = 0;
vector<int> ans(nums.size(), 0);
while(left <= right) {
if(nums[left] * nums[left] > nums[right] * nums[right]) {
ans[k--] = nums[left] * nums[left];
left++;
}
else {
ans[k--] = nums[right] * nums[right];
right--;
}
}
return ans;
}
};