[代码随想录]链表

链表

链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。
1.单链表

2.双链表(每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点)
在这里插入图片描述
3.循环链表
在这里插入图片描述

  • 定义节点
struct ListNode {
    
    
      int val;
      ListNode *next;
      ListNode() : val(0), next(nullptr) {
    
    }
      ListNode(int x) : val(x), next(nullptr) {
    
    }
      ListNode(int x, ListNode *next) : val(x), next(next) {
    
    }
  };


//1.通过自己定义的节点构造函数
ListNode* head = new ListNode(5);

//2.使用默认构造函数初始化节点:
ListNode* head = new ListNode();
head->val = 5;

1.设计链表

707.设计链表

设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:valnextval 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。

在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

设置一个虚拟头结点 比较简单

1.单链表

class MyLinkedList {
    
    
public:
    struct ListNoded{
    
    
        int val;
        ListNoded* next;
        ListNoded() : val(0),next(nullptr){
    
    }
        ListNoded(int x) : val(x),next(nullptr){
    
    }
        ListNoded(int x,ListNoded* next) : val(x),next(next){
    
    }
    };

    MyLinkedList() {
    
    
        head = new ListNoded(); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点
        size = 0;
    }
    
    int get(int index) {
    
    
        if(index < 0 || index >= size){
    
    
            return -1;
        }
        else{
    
    
            ListNoded* curGetNode = head->next;
            for(int i = 0;i < index; i++){
    
    
                curGetNode = curGetNode->next;
            }
            return curGetNode->val;
        }
    }
    
    void addAtHead(int val) {
    
    
        ListNoded* newHead = new ListNoded(val);
        newHead->next = head->next;
        head->next = newHead;
        size++;
    }
    
    void addAtTail(int val) {
    
    
        ListNoded* newTail = new ListNoded(val);
        ListNoded* curAddTailNode = head;
        for(;curAddTailNode->next != nullptr;){
    
    
            curAddTailNode = curAddTailNode->next;
        }
        curAddTailNode->next = newTail;
        size++;
    }
    
    void addAtIndex(int index, int val) {
    
      
         if(index == size){
    
    
            addAtTail(val);
        }
        else if(index == 0){
    
    
            addAtHead(val);
        }
        else if(index < 0){
    
    
            addAtHead(0);
        }
        else if(index > size){
    
    
            return;
        }
        else{
    
    
            ListNoded* newIndex = new ListNoded(val); 
            ListNoded* curAddIndexNode = head;
            for(int i = 0;i < index;i++){
    
    
                curAddIndexNode = curAddIndexNode->next;
            }
            newIndex->next = curAddIndexNode->next;
            curAddIndexNode->next = newIndex;
            size++;
        }
    }
    
    void deleteAtIndex(int index) {
    
    
        if(index < 0 || index >= size){
    
    
            return;
        }
        else{
    
    
            ListNoded* curDeleteNode = head;
            for(int i = 0;i < index;i++){
    
    
                curDeleteNode = curDeleteNode->next;
            }
            ListNoded* temp = curDeleteNode->next;
            curDeleteNode->next = curDeleteNode->next->next;
            delete temp;
            size--;
        }
    }
private:
    int size;
    ListNoded* head;
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */

2.双向链表

class MyLinkedList {
    
    
public:
    struct ListNoded{
    
    
        int val;
        ListNoded* next;
        ListNoded* prev;
        ListNoded() : val(0),next(nullptr),prev(nullptr){
    
    }
        ListNoded(int x) : val(x),next(nullptr),prev(nullptr){
    
    }
    };

    MyLinkedList() {
    
    
        head = new ListNoded(); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点
        end = new ListNoded();
        head->next = end;
        end->prev = head;
        size = 0;
    }
    
    int get(int index) {
    
    
        if(index < 0 || index >= size){
    
    
            return -1;
        }
        else{
    
    
            ListNoded* curGetNode = head->next;
            for(int i = 0;i < index; i++){
    
    
                curGetNode = curGetNode->next;
            }
            return curGetNode->val;
        }
    }
    
    void addAtHead(int val) {
    
    
        ListNoded* newHead = new ListNoded(val);
        newHead->next = head->next;
        newHead->prev = head;
        head->next->prev = newHead;
        head->next = newHead;
        size++;
    }
    
    void addAtTail(int val) {
    
    
        ListNoded* newTail = new ListNoded(val);
        ListNoded* curAddTailNode = head;
        for(;curAddTailNode->next != end;){
    
    
            curAddTailNode = curAddTailNode->next;
        }
        newTail->next = curAddTailNode->next;
        newTail->prev = curAddTailNode;
        curAddTailNode->next->prev = newTail;
        curAddTailNode->next = newTail;
        size++;
    }
    
    void addAtIndex(int index, int val) {
    
      
         if(index == size){
    
    
            addAtTail(val);
        }
        else if(index == 0){
    
    
            addAtHead(val);
        }
        else if(index < 0){
    
    
            addAtHead(0);
        }
        else if(index > size){
    
    
            return;
        }
        else{
    
    
            ListNoded* newIndex = new ListNoded(val); 
            ListNoded* curAddIndexNode = head;
            for(int i = 0;i < index;i++){
    
    
                curAddIndexNode = curAddIndexNode->next;
            }
            newIndex->next = curAddIndexNode->next;
            newIndex->prev = curAddIndexNode;
            curAddIndexNode->next->prev = newIndex;
            curAddIndexNode->next = newIndex;
            size++;
        }
    }
    
    void deleteAtIndex(int index) {
    
    
        if(index < 0 || index >= size){
    
    
            return;
        }
        else{
    
    
            ListNoded* curDeleteNode = head;
            for(int i = 0;i < index;i++){
    
    
                curDeleteNode = curDeleteNode->next;
            }
            ListNoded* temp = curDeleteNode->next;
            curDeleteNode->next->next->prev = curDeleteNode;
            curDeleteNode->next = curDeleteNode->next->next;
            delete temp;
            size--;
        }
    }
private:
    int size;
    ListNoded* head;
    ListNoded* end;
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */

2.改了一点点,使prev有用

class MyLinkedList {
    
    
public:
    struct ListNoded{
    
    
        int val;
        ListNoded* next;
        ListNoded* prev;
        ListNoded() : val(0),next(nullptr),prev(nullptr){
    
    }
        ListNoded(int x) : val(x),next(nullptr),prev(nullptr){
    
    }
    };

    MyLinkedList() {
    
    
        head = new ListNoded(); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点
        end = new ListNoded();
        head->next = end;
        end->prev = head;
        size = 0;
    }
    
    int get(int index) {
    
    
        if(index < 0 || index >= size){
    
    
            return -1;
        }
        else if(index <= (size - 1) / 2){
    
    
            ListNoded* curGetNode = head->next;
            for(int i = 0;i < index; i++){
    
    
                curGetNode = curGetNode->next;
            }
            return curGetNode->val;
        }
        else{
    
    
            ListNoded* curGetNode = end->prev;
            index = size - index - 1;//从后往前查找,查找次数要变
            for(int i = 0;i < index; i++){
    
    
                curGetNode = curGetNode->prev;
            }
            return curGetNode->val;
        }
    }
    
    void addAtHead(int val) {
    
    
        ListNoded* newHead = new ListNoded(val);
        newHead->next = head->next;
        newHead->prev = head;
        head->next->prev = newHead;
        head->next = newHead;
        size++;
    }
    
    void addAtTail(int val) {
    
    
        ListNoded* newTail = new ListNoded(val);
        ListNoded* curAddTailNode = head;
        for(;curAddTailNode->next != end;){
    
    
            curAddTailNode = curAddTailNode->next;
        }
        newTail->next = curAddTailNode->next;
        newTail->prev = curAddTailNode;
        curAddTailNode->next->prev = newTail;
        curAddTailNode->next = newTail;
        size++;
    }
    
    void addAtIndex(int index, int val) {
    
      
         if(index == size){
    
    
            addAtTail(val);
        }
        else if(index == 0){
    
    
            addAtHead(val);
        }
        else if(index < 0){
    
    
            addAtHead(0);
        }
        else if(index > size){
    
    
            return;
        }
        else if(index <= (size - 1) / 2){
    
    
            ListNoded* newIndex = new ListNoded(val); 
            ListNoded* curAddIndexNode = head;
            for(int i = 0;i < index;i++){
    
    
                curAddIndexNode = curAddIndexNode->next;
            }
            newIndex->next = curAddIndexNode->next;
            newIndex->prev = curAddIndexNode;
            curAddIndexNode->next->prev = newIndex;
            curAddIndexNode->next = newIndex;
            size++;
        }
        else{
    
    
            ListNoded* newIndex = new ListNoded(val); 
            ListNoded* curAddIndexNode = end;
            index = size - index;//!!!因为是要插入新节点到index的前面,所以新节点插入位置的前一个位置是index-1,后一个位置是index。所以从左往右遍历时,遍历到index-1的位置;从右往左遍历时,遍历到index(而不是index+1)。注意这点不同。
            for(int i = 0;i < index;i++){
    
    
                curAddIndexNode = curAddIndexNode->prev;
            }
            newIndex->prev = curAddIndexNode->prev;
            newIndex->next = curAddIndexNode;
            curAddIndexNode->prev->next = newIndex;
            curAddIndexNode->prev = newIndex;
            size++;
        }
    }
    
    void deleteAtIndex(int index) {
    
    
        if(index < 0 || index >= size){
    
    
            return;
        }
        else if(index <= (size - 1) / 2){
    
    
            ListNoded* curDeleteNode = head;
            for(int i = 0;i < index;i++){
    
    
                curDeleteNode = curDeleteNode->next;
            }
            ListNoded* temp = curDeleteNode->next;
            curDeleteNode->next->next->prev = curDeleteNode;
            curDeleteNode->next = curDeleteNode->next->next;
            delete temp;
            size--;
        }
        else{
    
    
            ListNoded* curDeleteNode = end;
            index = size - index - 1;//指向待删除节点的后一个位置,所以减1
            for(int i = 0;i < index;i++){
    
    
                curDeleteNode = curDeleteNode->prev;
            }
            ListNoded* temp = curDeleteNode->prev;
            curDeleteNode->prev->prev->next = curDeleteNode;
            curDeleteNode->prev = curDeleteNode->prev->prev;
            delete temp;
            size--;
        }
    }
private:
    int size;
    ListNoded* head;
    ListNoded* end;
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */

2.移除链表元素

在这里插入图片描述

  • 记得delete删除节点

203.移除链表元素

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点

1.方法1:直接使用原来的链表来进行删除操作

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    
    
public:
    ListNode* removeElements(ListNode* head, int val) {
    
    
        ListNode* deleteNode;
        while(head != NULL && head->val == val){
    
    
                deleteNode = head;
                head = head->next;
                delete deleteNode;
            }
        ListNode* current = head;
        while(current != NULL && current->next != NULL){
    
    
            if(current->next->val == val){
    
    
                deleteNode = current->next;
                current->next = current->next->next;
                delete deleteNode;
            } 
            else{
    
    
                current = current->next;
            }         
        } 
        return head;
    }
};

2.方法2:设置一个虚拟头结点在进行移除节点操作:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    
    
public:
    ListNode* removeElements(ListNode* head, int val) {
    
    
        ListNode* virNode = new ListNode(0,head);
        ListNode* currentNode = virNode;
        while(currentNode->next != NULL){
    
    
            if(currentNode->next->val == val){
    
    
                ListNode* deleteNode = currentNode->next;
                currentNode->next = currentNode->next->next;
                delete deleteNode;
            }
            else{
    
    
                currentNode = currentNode->next;
            }
        }
        head = virNode->next;
        delete virNode;
        return head;
    }
};

3.方法3:**递归 **

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    
    
public:
    ListNode* removeElements(ListNode* head, int val) {
    
    
        if(head == NULL){
    
    
            return head;
        }
        else{
    
    
            head->next = removeElements(head->next,val);
            if(head->val == val){
    
    
                return head->next;
            }
            else{
    
    
                return head;
            }
        }
    }
};

3.翻转链表

206. 反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

img

1.双指针法
```
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    
    
public:
    ListNode* reverseList(ListNode* head) {
    
    
        ListNode* slowNode = NULL;
        ListNode* fastNode = head;
        ListNode* curNode;
        while(fastNode != NULL){
    
    
            curNode = fastNode;
            fastNode = fastNode->next;
            curNode->next = slowNode;
            slowNode = curNode;
        }
    return slowNode;
    }
};

2.递归1

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    
    
public:
    ListNode* reverse(ListNode* slowNode,ListNode* fastNode){
    
    
        if(fastNode == NULL) return slowNode;
        ListNode* curNode;
        curNode = fastNode;
        fastNode = fastNode->next;
        curNode->next = slowNode;
        slowNode = curNode;
        return reverse(slowNode,fastNode);
    }

    ListNode* reverseList(ListNode* head) {
    
    
        ListNode* slowNode = NULL;
        ListNode* fastNode = head;
        return reverse(slowNode,fastNode);
    }
};

3.递归2

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    
    
public:
    ListNode* reverseList(ListNode* head) {
    
    
        if(head == nullptr) return nullptr;
        if(head->next == nullptr) return head;
        ListNode* last = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return last;
    }
};

递归方法还需要学习

4.两两交换链表中的节点

24. 两两交换链表中的节点

给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

img

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    
    
public:
    ListNode* swapPairs(ListNode* head) {
    
    
        ListNode* virNode = new ListNode(0,head);
        if(head == nullptr || head->next == nullptr) return head;
        ListNode* slowNode = virNode;
        ListNode* fastNode = head;
        ListNode* curSlow,*curFast;
        while(fastNode != NULL && fastNode->next != NULL){
    
    //双数fastNode不能等于NULL,单数fastNode->next不能等于NULL
            curSlow = slowNode;
            curFast = fastNode;

            fastNode = fastNode->next->next;

            curSlow->next = curFast->next;
            curFast->next->next = curFast;
            curFast->next = fastNode;
            
            slowNode = curFast;
        }
        head = virNode->next;
        delete virNode;
        return head;
    }
};

5.删除链表的倒数第N个节点

19. 删除链表的倒数第 N 个结点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

img

1.暴力破解

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    
    
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
    
    
        ListNode* virNode = new ListNode(0,head);
        ListNode* curNode = virNode;
        int index = 0;
        if(head == nullptr || head->next == nullptr)return nullptr;
        while(curNode->next != nullptr){
    
    //统计个数
            curNode = curNode->next;
            index++;
        }
        curNode = virNode;
        for(int i = 0;i < index - n;i++){
    
    //删除
            curNode = curNode->next;
        }
        ListNode* deleteNode = curNode->next;
        curNode->next = curNode->next->next;
        delete deleteNode;
        head = virNode->next;
        delete virNode;
        return head;
    }
};

2.双指针(镜像思想,找到对称过来要删除的点,然后将两个指针同时往后移,使慢指针指向删除点前一位)

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
    
    
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
    
    
        ListNode* virNode = new ListNode(0,head);
        ListNode* slowNode = virNode;
        ListNode* fastNode = virNode;
        if(head == nullptr || head->next == nullptr)return nullptr;
        while(fastNode != nullptr && n){
    
    //利用对称思想,找到对称过来要删除的点,然后将两个指针同时往后移,使慢指针指向删除点前一位
            fastNode = fastNode->next;
            n--;
        }
        while(fastNode->next != nullptr){
    
    
            slowNode = slowNode->next;
            fastNode = fastNode->next;
        }
        ListNode* deleteNode = slowNode->next;
        slowNode->next = slowNode->next->next;
        delete deleteNode;
        return virNode->next;
    }
};

6.链表相交

  • 交点不是数值相等,而是指针相等

面试题 02.07. 链表相交

给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null

图示两个链表在节点 c1 开始相交**:**

img

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构

1.暴力for循环

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    
    
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    
    
        for(ListNode* curA = headA;curA != NULL;curA = curA->next){
    
    
            for(ListNode* curB = headB;curB != NULL;curB = curB->next){
    
    
                if(curA == curB)return curA;
            }
        }
        return NULL;
    }
};

2.根据代码随想录思路,很巧妙,假设A长于B,长出前面部分去掉,看后面有没有重叠

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    
    
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    
    
        ListNode* curA = headA;
        ListNode* curB = headB;
        int indexA = 0;
        int indexB = 0;
        while(curA != NULL){
    
    
            curA = curA->next;
            indexA++;
        }
        while(curB != NULL){
    
    
            curB = curB->next;
            indexB++;
        }

        curA = headA;
        curB = headB;//重新到开头
        
        if(indexA >= indexB) {
    
    
            int cha = indexA - indexB;
            while(cha--){
    
    
                curA = curA->next;
            }
            while(curA != NULL || curB != NULL){
    
    
                if(curA == curB)return curA;
                curA = curA->next;
                curB = curB->next;
            }
        }
        else{
    
    
            int cha = indexB - indexA;
            while(cha--){
    
    
                curB = curB->next;
            }
            while(curA != NULL || curB != NULL){
    
    
                if(curA == curB)return curA;
                curA = curA->next;
                curB = curB->next;
            }
        }
        return NULL;
    }
};

3.再改进

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    
    
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    
    
        ListNode* curA = headA;
        ListNode* curB = headB;
        int indexA = 0;
        int indexB = 0;
        while(curA != NULL){
    
    
            curA = curA->next;
            indexA++;
        }
        while(curB != NULL){
    
    
            curB = curB->next;
            indexB++;
        }
        
        if(indexB > indexA){
    
    
            swap(headA,headB);
            swap(indexA,indexB);
        }

        curA = headA;
        curB = headB;//重新到开头
        
        int cha = indexA - indexB;
        while(cha--){
    
    
            curA = curA->next;
        }
        while(curA != NULL || curB != NULL){
    
    
            if(curA == curB)return curA;
            curA = curA->next;
            curB = curB->next;
        }
        return NULL;
    }
};

7.环形链表

142. 环形链表 II

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos-1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改 链表。

示例 1:

img

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

1.自己思路加提示(看了一句提示,让快指针和慢指针同时进行,但是快指针比慢指针快)

想了很久,这句提示就是解题关键

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    
    
public:
    ListNode *detectCycle(ListNode *head) {
    
    
        ListNode* virHead = new ListNode(0,head);
        ListNode* slowNode = virHead;
        ListNode* fastNode = virHead;
        ListNode* findNode = virHead;//查找入口
        while(fastNode != NULL && fastNode->next != NULL){
    
    
            slowNode = slowNode->next;//要快指针比慢指针走得快一些看他们能不能相遇
            fastNode = fastNode->next->next;
            if(slowNode == fastNode){
    
         
                while(fastNode != findNode){
    
    //一直循环,每次绕到原来跟慢指针一样位置为一圈,查找入口位置
                    fastNode = fastNode->next;
                    if(fastNode == slowNode){
    
    
                        findNode = findNode->next;
                    }
                }
                return findNode;
            }
        }
        return NULL;
    }
};

2.根据代码随想录思路,画图用数学方式解决
具体画图看代码随想录,也可以看leetcode后面详细画图

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
    
    
public:
    ListNode *detectCycle(ListNode *head) {
    
    
        ListNode* virHead = new ListNode(0,head);
        ListNode* slowNode = virHead;
        ListNode* fastNode = virHead;
        ListNode* findNode = virHead;//查找入口
        while(fastNode != NULL && fastNode->next != NULL){
    
    
            slowNode = slowNode->next;//要快指针比慢指针走得快一些看他们能不能相遇
            fastNode = fastNode->next->next;
            if(slowNode == fastNode){
    
         
                while(fastNode != findNode){
    
    //根据代码随想录数学公式
                    fastNode = fastNode->next;
                    findNode = findNode->next;
                }
                return findNode;
            }
        }
        return NULL;
    }
};

猜你喜欢

转载自blog.csdn.net/m0_53953432/article/details/128064120