快慢指针的应用

核心思想

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

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

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;
}
相关推荐
我不是懒洋洋3 小时前
【经典题目】链表OJ(相交链表、环形链表、环形链表II、随机链表的复制)
c语言·开发语言·数据结构·链表·ecmascript·visual studio
m0_716765233 小时前
数据结构--循环链表、双向链表的插入、删除、查找详解
开发语言·数据结构·c++·学习·链表·青少年编程·visual studio
wunaiqiezixin4 小时前
链表多项式大整数-BigInt
数据结构·c++·链表
jinyishu_4 小时前
链表经典算法题(2)
c语言·数据结构·链表
_日拱一卒5 小时前
LeetCode:142环形链表Ⅱ
算法·leetcode·链表
jinyishu_20 小时前
几道链表经典算法题
c语言·数据结构·算法·链表
_日拱一卒1 天前
LeetCode:206反转链表
算法·leetcode·链表
我不是懒洋洋1 天前
【经典题目】链表OJ(轮转数组、返回倒数第k个节点、链表的回文结构)
c语言·开发语言·数据结构·算法·链表·visual studio
想带你从多云到转晴2 天前
04、数据结构与算法---双向链表
java·数据结构·算法·链表