链表类问题


基础链表题目

206. 反转链表

使用双指针法解决链表问题

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

用两个指针指向head节点,先让第一个指针走n-1步,然后再让两个指针同时走,直到第一个指针的next为nullptr,此时第二个指针指向的就是要删除的节点。这里为了减少不必要的判断,我们把第二个指针设为二级指针。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* pfirst = head;
        ListNode** psecond = &head;
        for (int i = 1;i < n;++i) {
            pfirst = pfirst->next;
        }
        while (pfirst->next) {
            psecond = &(*psecond)->next;
            pfirst = pfirst->next;
        }
        *psecond = (*psecond)->next;
        return head;
    }
};

160. 相交链表

先遍历两个链表获取它们的长度lenA和lenB,然后先让指针ptrA在长链表(假设长链表是A,短链表是B)上走lenA - lenB步,再让指针ptrA和ptrB分别在长链表和短链表上移动,二者相遇时就是交叉点。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int lenA = getLength(headA);
        int lenB = getLength(headB);
        if (lenA > lenB) {
            for (int i = 0;i < lenA - lenB;++i) {
                headA = headA->next;
            }
        } else {
            for (int i = 0;i < lenB - lenA;++i) {
                headB = headB->next;
            }
        }

        while (headA && headB) {
            if (headA == headB) {
                return headA;
            } else {
                headA = headA->next;
                headB = headB->next;
            }
        }
        return nullptr;
    }
private:
    int getLength(ListNode* head) {
        int len = 0;
        while (head) {
            ++len;
            head = head->next;
        }
        return len;
    }
};

使用二级指针操作链表

2. 两数相加

class Solution {
public:
    ListNode* addTwoNumbers(ListNode* l1, ListNode* l2) {
        auto p1 = l1;
        auto p2 = l2;
        ListNode* ph = nullptr;
        ListNode** curr = &ph;
        int carry = 0;
        while (p1 || p2) {
            int x = p1 ? p1->val : 0;
            int y = p2 ? p2->val : 0;
            int val = x + y + carry;
            carry = val / 10;
            val = carry ? val - 10 : val;
            *curr = new ListNode(val);
            curr = &(*curr)->next;
            if (p1) p1 = p1->next;
            if (p2) p2 = p2->next;
        }
        if (carry) *curr = new ListNode(1);
        return ph;
    }
};

LeetCode 21. 合并两个有序链表

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
        ListNode* head = nullptr;
        ListNode** curr = &head;
        auto p1 = l1;
        auto p2 = l2;
        while (p1 && p2) {
            if (p1->val < p2->val) {
                *curr = p1, p1 = p1->next;
            } else {
                *curr = p2, p2 = p2->next;
            }
            curr = &(*curr)->next;
        }
        if (p1) *curr = p1;
        if (p2) *curr = p2;
        return head;
    }
};

相似题目
23. 合并K个有序链表
21题的进阶版,每次迭代,分别合并链表数组中第一个和最后一个链表,当数组中仅剩一个链表时退出,均摊时间复杂度为\(O(n\log n)\)

148. 排序链表

重新排列链表

86. 分隔链表

class Solution {
public:
    ListNode* partition(ListNode* head, int x) {
        ListNode* newHead = nullptr;
        ListNode** prev = &newHead;
        for (auto iter = &head; *iter;) {
            if ((*iter)->val < x) {
                *prev = *iter;
                prev = &(*prev)->next;
                *iter = (*iter)->next;
            } else {
                iter = &(*iter)->next;
            }
        }
        *prev = head;
        return newHead;
    }
};

相关题目:
328. 奇偶链表

链表与其他数据结构的结合

138. 复制带随机指针的链表

/*
// Definition for a Node.
class Node {
public:
    int val;
    Node* next;
    Node* random;
    
    Node(int _val) {
        val = _val;
        next = NULL;
        random = NULL;
    }
};
*/
class Solution {
public:
    Node* copyRandomList(Node* head) {
        Node* pHead = head;

        while (head) {
            randomMap[head] = new Node(head->val);
            head = head->next;
        }
        
        Node* newHead = randomMap[pHead];
        Node* qHead = newHead;
        while (qHead && pHead) {
            qHead->next = randomMap[pHead->next];
            qHead->random = randomMap[pHead->random];
            pHead = pHead->next;
            qHead = qHead->next;
        }

        return newHead;
    }
private:
    unordered_map randomMap;
};