代码随想录刷题总结:链表

这篇博客详细介绍了链表的各种操作,包括删除所有等于特定值的节点、设计链表、反转链表、两两交换链表节点、找到链表的交点和环等。通过迭代和递归两种方法展示了不同问题的解决方案,涵盖了链表的基本特性和操作技巧。
摘要由CSDN通过智能技术生成

链表处理的细节较多,故在此大多给出具体代码。

一、修改链表

203. 移除链表中所有等于给定值的节点

细节注意:设置 dummy head 简化过程,并注意不要访问空指针。

// iteration
class Solution {
public:
    ListNode* removeElements(ListNode* head, const int val) {
        ListNode* dummyHead = new ListNode(0, head);
        ListNode* cur = dummyHead;
        while (nullptr != cur->next) {
            if (val == cur->next->val) {
                ListNode *next = cur->next;
                cur->next = next->next;
                delete next;
            } else {
                cur = cur->next;
            }
        }
        return dummyHead->next;
    }
};
// recursion
class Solution {
public:
    ListNode* removeElements(ListNode* head, const int val) {
        if (head == nullptr) {
            return head;
        }
        head->next = removeElements(head->next, val);
        if (val == head->val) {
            ListNode *prev = head;
            head = head->next;
            delete prev;
        }
        return head;
    }
};

707. 设计链表

注意单链表和双向链表的实现区别,添加和删除节点时需要前序节点的信息。

206. 反转链表

// iteration
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* curr = head, * prev = nullptr;
        while (nullptr != curr) {
            ListNode *next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
};
// recursion
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if (nullptr == head || nullptr == head->next)
            return head;
        ListNode *rHead = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return rHead;
    }
};

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

// iteration
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if (head == nullptr || head->next == nullptr) {
            return head;
        }
        // Firstly, recursively process the part after newHead, then swap head and newHead
        ListNode* newHead = head->next;
        head->next = swapPairs(newHead->next);
        newHead->next = head;
        return newHead;
    }
};
// recursion
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* temp = dummyHead;
        // At the beginning of each loop, temp points to the predecessor node of the two nodes to be swapped
        while (temp->next != nullptr && temp->next->next != nullptr) {
            ListNode* node1 = temp->next;
            ListNode* node2 = temp->next->next;
            temp->next = node2;
            node1->next = node2->next;
            node2->next = node1;
            temp = node1;
        }
        ListNode* result = dummyHead->next;
        delete dummyHead;
        return result;
    }
};

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

双指针法,让靠前的指针领先靠后的指针 n + 1 个位置,当靠前的指针到达 NULL 时,删除靠后的指针的后继节点即可。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummy = new ListNode(0, head);
        ListNode* first = head;
        ListNode* second = dummy;
        for (int i = 0; i < n; ++i) {
            first = first->next;
        }
        while (first) {
            first = first->next;
            second = second->next;
        }
        second->next = second->next->next;
        ListNode* ans = dummy->next;
        delete dummy;
        return ans;
    }
};

二、获取链表属性

面试题 02.07. 判定链表是否有交点并返回交点

双指针法,假定一个链表的尾端连接在另一个链表的首端,则两个指针最终会在交点或同时为 nullptr.

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *pA = headA, *pB = headB;
        while (pA != pB) {
            pA = pA == nullptr ? headB : pA->next;
            pB = pB == nullptr ? headA : pB->next;
        }
        return pA;
    }
};

141. 判断单链表是否有环

见下一题。

142. 判断单链表是否有环并返回入环节点

快慢指针法,让快慢指针同时从 head 开始,若二者能相遇,则说明有环。判定有环后,令一个指针从 head 开始前进,另一个节点从相遇点开始前进,可证明若二者相遇,则相遇点为入环点。

证明:假设 head 到入环点要走 x 步,入环点到相遇点要走 y 步,相遇点到入环点要走 z 步。则易知快慢指针相遇时,慢指针走了 x + y 步,快指针走了 x + 2 * y + z 步,故有 2 * (x + y) = x + 2 * y + z,即 x = z.

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast != NULL && fast->next != NULL) {
            slow = slow->next;
            fast = fast->next->next;
            if (slow == fast) {
                ListNode* index1 = fast;
                ListNode* index2 = head;
                while (index1 != index2) {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index2;
            }
        }
        return NULL;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值