快慢指针的应用

核心思想

快慢指针的核心思想是利用两个移动速度不同的指针(通常快指针每次走两步,慢指针每次走一步,在遍历过程中通过他们的位置关系或相遇情况来解决问题。通常在数组和链表中有应用。(快指针用来探路,慢指针用来定位)

一、快慢指针在链表中的应用

1.判断链表是否有环

环形链表

通过快慢指针来判断链表是否有环。

思路:创建两个指针slow,fast,遍历链表。slow每次走一步,fast每次走两步,若链表有环,则快慢指针在进环后,快指针总会追上慢指针。若链表无环,则fast走向末尾。

c 复制代码
bool hasCycle(struct ListNode *head) {
    struct ListNode* slow,*fast;
    slow = fast = head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast = fast->next->next;
        if(slow==fast)
        {
            return true;
        }
    }
    return false;
}

拓展问题 :1.为什么一定会相遇,有没有可能会错过,永远追不上,请证明。

2.slow一次走1步,fast一次走3,4,5,步 n步,请证明。

证明:(1)

(2)

结论:一定能追上,N偶数第一轮就追上,N奇数,C-1偶数,第二轮追上。

2.返回链表入环的节点

环形链表2

c 复制代码
struct ListNode *detectCycle(struct ListNode *head) {
    struct ListNode *slow,*fast;
    slow = fast = head;
    while(fast&&fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
        if(slow==fast)
        {
            struct ListNode *meet = slow;
            while(meet!=head)
            {
                meet = meet->next;
                head = head->next;
            }
            return meet;
        }
    }
    return NULL;
}

3.寻找链表的中点

链表的中间节点

通过快慢指针来返回链表中间节点,或返回第二个中间节点,可以通过快慢指针的方式,fast=2slow。(分为奇数和偶数个节点)

c 复制代码
typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {
    ListNode* slow, *fast;
    slow = fast = head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    return slow;
}

4.寻找倒数第k个节点

寻找倒数第k个节点

先让快指针走k步,,然后快慢指针同步移动,当快指针到达末尾时,慢指针指向的即为倒数第k个节点。

c 复制代码
typedef struct ListNode ListNode;
int kthToLast(struct ListNode* head, int k) {
    ListNode *slow,*fast;
    slow = fast=head;
    while(k--)
    {
        fast=fast->next;
    }
    while(fast)
    {
        slow=slow->next;
        fast=fast->next;
    }
    return slow->val;
}

5.随机链表的复制

随机链表的复制

c 复制代码
struct Node* copyRandomList(struct Node* head) {
	struct Node *cur = head;
    //拷贝节点插入在原节点的后面
    while(cur)
    {
        struct Node *copy = (struct Node*)malloc(sizeof(struct Node));

        copy->val = cur->val;
        copy->next = cur->next;
        cur->next = copy;

        cur = copy->next;
    }
    //控制random
    cur = head;
    while(cur)
    {
        struct Node* copy = cur->next;
        if(cur->random==NULL)
        {
            copy->random=NULL;
        }
        else{
            copy->random = cur->random->next;
        }
        cur = copy->next;
    }
    //把拷贝节点取下来尾插成为新链表,然后恢复原链表,不恢复也可以
    struct Node* copyhead,*copytail;
    copyhead = copytail = NULL;
    cur = head;
    while(cur)
    {
        struct Node* copy = cur->next;
        struct Node* next = copy->next;

        if(copytail==NULL)
        {
            copyhead = copytail = copy;
        }
        else
        {
            copytail->next = copy;
            copytail = copytail->next;
        }
        cur->next = next;
        cur=next;
    }
    return copyhead;
}



二、快慢指针在数组中的应用

1.移除元素

在有序数组中,慢指针指向"已处理区间"的末尾,快指针用于探索新元素,当快指针遇到不重复(或不等于目标值)的元素时,将其赋值给慢指针并移动慢指针。
移除数组中的重复元素

c 复制代码
int removeDuplicates(int* nums, int numsSize) {
    int slow = 0;
    for(int fast=1;fast<numsSize;fast++)
    {
        if(nums[fast]!=nums[slow])
        {
            slow++;
            nums[slow]=nums[fast];
        }
    }
    return slow+1;
}
相关推荐
许彰午1 天前
02-手写链表、栈、队列——不依赖任何集合框架
数据结构·链表·面试
MegaDataFlowers1 天前
141.环形链表
数据结构·链表
澈2072 天前
C++ list容器完全指南
数据结构·c++·链表
纽扣6673 天前
【算法进阶之路】链表进阶:删除、合并、回文与排序全解析
数据结构·算法·链表
纽扣6673 天前
【算法进阶之路】链表核心:快慢指针与反转链表专题精讲
数据结构·c++·算法·链表
海清河晏1113 天前
数据结构 | 链式队列
开发语言·数据结构·链表
风筝在晴天搁浅4 天前
LeetCode 92.反转链表Ⅱ
算法·leetcode·链表
WL_Aurora4 天前
Python 算法基础篇之链表
python·算法·链表
jinyishu_4 天前
链表经典OJ题
c语言·数据结构·算法·链表
jieyucx4 天前
Go 零基础数据结构:链表的增删改查(像串珠子一样简单)
数据结构·链表·golang