顺序表
27. 移除元素 - 力扣(LeetCode)
1.暴力解法
2.空间换时间(新开一个顺序表,来存储)
3.对撞双指针解法
左指针找等于 val 的元素,右指针找不等于 val 的元素,找到后交换,把 val 全部挤到数组尾部,最终 left 就是有效元素个数 k.

cpp
void swap(int *a,int *b)
{
int tmp=*a;
*a=*b;
*b=tmp;
}
//调用:swap(&x,&y);
int removeElement(int* nums, int numsSize, int val) {
int right=numsSize-1,left=0;
if(numsSize==0)
return 0;
while(right>=left)
{
if(nums[left]!=val)left++;
else swap(&nums[left],&nums[right--]);
}
return left;
}
26. 删除有序数组中的重复项 - 力扣(LeetCode)
快慢双指针解法
left(慢指针) :指向已去重区间的最后一个有效元素下标 ,初始left = 0(第一个元素天然保留);
right(快指针) :用来向后遍历查找新的不重复元素,初始right = 1。
循环条件:right < numsSize,右指针没走完数组就循环:
- 若
nums[right] != nums[left]:说明right找到新的不重复数字left++(有效区间向后扩容一位)nums[left] = nums[right](把新元素r存到有效区末尾)right++继续往后遍历
- 若
nums[right] == nums[left]:当前是重复元素,直接right++跳过。

cpp
int removeDuplicates(int* nums, int numsSize) {
int left=0,right=1;
while(right<numsSize&&left<right)
{
if(nums[right]!=nums[left])
nums[++left]=nums[right++];
else right++;
}
return left+1;
}
链表
876. 链表的中间结点 - 力扣(LeetCode)
快慢双指针
slow(慢指针)、fast(快指针)都从链表首结点 head 出发:
- 慢指针:每次向后走 1 步
- 快指针:每次向后走 2 步
① 链表结点总数为奇数(例:5 个结点:1-2-3-4-5)
- 结束时:
fast落在最后一个结点 ,fast->next=NULL→ 循环终止 slow恰好停在唯一中间结点(3),直接返回 slow,符合题意。
② 链表结点总数为偶数(例:6 个结点:1-2-3-4-5-6)
- 结束时:
fast=NULL(走到末尾空地址)→ 循环终止 slow停在靠后那个中间结点(4),满足题目:偶数时返回第二个中间结点的要求。

cpp
struct ListNode* middleNode(struct ListNode* head) {
struct ListNode* slow=head;
struct ListNode* fast=head;
while(fast&&fast->next)
{
slow=slow->next;
fast=fast->next->next;
}
return slow;
}
面试题 02.02. 返回倒数第 k 个节点 - 力扣(LeetCode)
快慢双指针
1.初始化指针:慢指针 slow、快指针 fast 同时指向链表头结点 head。
2.快指针先行 k 步:通过循环让 fast 向后移动 k 个结点,使 fast 与 slow 两个指针之间固定间隔 k 个节点。
3.双指针同步后移:在 fast 不为空的条件下,fast 和 slow 每次同步向后移动一个结点;当 fast 遍历至链表尾部空地址时停止循环。
4.返回结果:循环结束时 slow 恰好指向倒数第 k 个结点,返回该结点的数据域 slow->val。

cpp
int kthToLast(struct ListNode* head, int k) {
struct ListNode* slow=head;
struct ListNode* fast=head;
int count=0;
while(count<k)
{
fast=fast->next;
count++;
}
while(fast)
{
fast=fast->next;
slow=slow->next;
}
return slow->val;
}