双指针算法 (力扣)
26. 删除有序数组中的重复项
给你一个 升序排列 的数组 nums
,请你** 原地** 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。
数组双指针
快慢指针实现:
让慢指针 slow
走在后面,快指针 fast
走在前面探路,找到一个不重复的元素就告诉 slow
并让 slow
前进一步。这样当 fast
指针遍历完整个数组 nums
后,nums[0..slow]
就是不重复元素
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
if(nums.size() == 0) return 0;
int slow = 0,fast = 0;
while(fast < nums.size()){
if(nums[fast] != nums[slow]){
slow ++;
nums[slow] = nums[fast];
}
fast ++;
}
//注意数组索引长度是slow + 1
return slow + 1;
}
};
利用相邻元素是否相同解决
class Solution {
public:
int removeDuplicates(vector<int>& nums) {
int k = 0;
for(int i = 0;i <nums.size();i ++){
if(i == 0 || nums[i]!= nums[i - 1]) nums[k ++] = nums[i];
}
return k;
}
};
83. 删除排序链表中的重复元素
给定一个已排序的链表的头 head
, 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。
思路和26删除数组重复项一样
class Solution {
public:
ListNode* deleteDuplicates(ListNode* head) {
if(head == NULL) return head;
auto slow = head,fast = head;
while(fast != NULL){
if(fast->val != slow->val){
slow->next = fast;
slow = slow->next;
}
fast = fast->next;
}
slow->next = NULL;//注意链表需要断开后面重复元素的连接
return head;
}
};
283. 移动零
给定一个数组 nums
,编写一个函数将所有 0
移动到数组的末尾,同时保持非零元素的相对顺序。
请注意 ,必须在不复制数组的情况下原地对数组进行操作。
可以直接复用 27. 移除元素 的解法,先移除所有 0,然后把最后的元素都置为 0,就相当于移动 0 的效果
class Solution{
public:
void moveZeroes(vector<int> &nums){
int k = 0;
for(auto x: nums){
if(x) nums[k ++] = x;
}
while(k < nums.size()) nums[k ++] = 0;
}
};
27. 移除元素
给你一个数组 nums
和一个值 val
,你需要 原地 移除所有数值等于 val
的元素,并返回移除后数组的新长度。
不要使用额外的数组空间,你必须仅使用 O(1)
额外空间并 原地 修改输入数组。
元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int k = 0;
for(int i = 0;i < nums.size(); i ++){
if(nums[i] != val) nums[k ++] = nums[i];
}
return k;
}
};