链表操作

1. 找到链表的中间节点

思路:用两个指针,初始时都指向链表头,然后一个每次往前走一步,另一个每次往前走两步,走两步的指针走到尾时,走一步的指针的位置即为链表的中间位置

    Node* findMiddleNode(Node* pHead) {
        if (pHead == nullptr) {
            return(pHead);
        }
        if (pHead->next == nullptr) {
            return(pHead);
        }
        Node *pSlow = pHead;
        Node *pFast = pHead;

        while (pFast->next != nullptr && pFast->next->next!=nullptr) {
            pSlow = pSlow->next;
            pFast = pFast->next->next;
        }

        return(pSlow);
    }
View Code

2. 找到倒数第K个节点

思路:设置两个指针,让其中一个指针先走K步,然后两个指针等速往前走,先走的指针走到尾时,后走指针的位置即为倒数第K个节点

    Node* findReverseKNode(Node* pHead, int k) {
        Node* kNode = nullptr;
        Node* p = pHead;

        for (int i = 0; i < k-1; i++) {
            if (p == nullptr) {
                return(nullptr);
            }
            p = p->next;
        }

        kNode = pHead;
        while (p != nullptr) {
            p = p->next;
            kNode = kNode->next;
        }

        return(kNode);
    }
View Code

3. 链表倒转

思路:假设p1->p2->p3,倒转p1->p2的时候,需要记录p3

    Node* reverseList(Node* pHead) {
        if (pHead == nullptr || pHead->next == nullptr) {
            return(nullptr);
        }

        Node* p = pHead;
        Node* pNext = p->next;
        while (pNext != nullptr) {
            Node *pNextNext = pNext->next;
            pNext->next = p;
            p = pNext;
            pNext = pNextNext;
        }

        pHead->next = nullptr;
        pHead = p;
        return(pHead);
    }
View Code

4. 找到两个链表的交叉点

思路:如果两个链表交叉,则可以想象两个链表构成Y形,只是Y的分叉部分不一样长,所以解法为先求出两个链表的长度l1和l2,然后求差值|l1-l2|,设置两个指针分别指向两个链表头,让指向长链表的指针先走|l1-l2|步,然后两个指针再一起走,判断是否相等

    Node* getCrossNode(Node* pHead1, Node* pHead2) {
        Node* p1 = pHead1;
        Node* p2 = pHead2;
        if (p1 == nullptr || p2 == nullptr) {
            return(nullptr);
        }

        int l1 = 0;
        while (p1 != nullptr) {
            l1++;
            p1 = p1->next;
        }

        int l2 = 0;
        while (p2 != nullptr) {
            l2++;
            p2 = p2->next;
        }

        p1 = pHead1;
        p2 = pHead2;
        if (l2 > l1) {
            for (int i = 0; i < (l2 - l1); i++) {
                p2 = p2->next;
            }
        }
        else if (l1 > l2) {
            for (int i = 0; i < (l1 - l2); i++) {
                p1 = p1->next;
            }
        }

        while (p1 != nullptr && p2 != nullptr && p1 != p2) {
            p1 = p1->next;
            p2 = p2->next;
        }

        if (p1 == p2) {
            return(p1);
        }
        else {
            return(nullptr);
        }
    }
View Code

5. 判断是否存在环

思路:设置两个指针,同时指向表头,一个每次往前走一步,另一个走两步,如果两个指针相遇,即存在环

    bool doesContainLoop(Node* pHead) {
        if (pHead == nullptr || pHead->next == nullptr) {
            return(false);
        }

        Node* pSlow = pHead;
        Node* pFast = pHead;
        while (pFast != nullptr && pFast->next != nullptr && pSlow != pFast) {
            pSlow = pSlow->next;
            pFast = pFast->next->next;
        }

        if (pSlow == pFast) {
            return(true);
        }
        else {
            return(false);
        }
    }
View Code

6. 求环的起点

思路:

假设两个指针,在Z点相遇,相遇时慢的走了m圈,快的走了n圈,则(a+b+m*r)*2=a+b+n*r,可以推导出a=(n-2m)*r-b=(n-2m-1)*r+r-b=(n-2m-1)*r+c,所以可以设置两个指针,一个从表头X点开始走,另一个从相遇点Z开始走,两个指针相遇的位置即为环的起点

    Node* getLoopOrigin(Node* pHead) {
        if (pHead == nullptr || pHead->next == nullptr) {
            return(nullptr);
        }

        Node* pSlow = pHead;
        Node* pFast = pHead;
        while (pFast != nullptr && pFast->next != nullptr && pSlow != pFast) {
            pSlow = pSlow->next;
            pFast = pFast->next->next;
        }

        if (pSlow != pFast) {
            return(nullptr);
        }

        Node* p = pHead;
        while (p != pSlow) {
            p = p->next;
            pSlow = pSlow->next;
        }

        return(p);
    }
View Code

7. 求环的长度

思路:让两个指针都从相遇点开始走,步速为2的指针和步速为1的指针再次相遇时,步速为1的指针所走的长度即为环的长度

    int getLoopLength(Node* pHead) {
        if (pHead == nullptr || pHead->next == nullptr) {
            return(0);
        }

        Node* pSlow = pHead;
        Node* pFast = pHead;
        while (pFast != nullptr && pFast->next != nullptr && pSlow != pFast) {
            pSlow = pSlow->next;
            pFast = pFast->next->next;
        }

        if (pSlow != pFast) {
            return(0);
        }
        
        int loopLen = 0;
        pSlow = pSlow->next;
        pFast = pFast->next->next;
        while (pSlow != pFast) {
            loopLen++;
            pSlow = pSlow->next;
            pFast = pFast->next->next;
        }
        loopLen++;
        return(loopLen)
    }
View Code

8. 求有环链表的长度

思路:6求出了环的起点,可以得出无环部分的长度,加上7的环的长度,即为有环链表的长度

原文地址:https://www.cnblogs.com/guo-xiang/p/10082028.html