[TOC]

​ 本文主要记录链表的相交、合并、排序的相关LeetCode题目的实现代码,直接给出本文各个题目的答案,供有需求的读者学习或复制。

一、链表复制

138. 复制带随机指针的链表(中等难度)

剑指 Offer 35. 复杂链表的复制(中等难度)

class Solution {
public:
    /*难点:random可能指向未创建的节点*/
    Node* copyRandomList(Node* head) {
        if(head==NULL) return NULL;
        // 第一步:遍历原始链表,创建新节点并且存入哈希表中
        unordered_map<Node*,Node*> dict;//key:原有链表节点 value:新创建链表节点
        Node* cur=head;
        while(cur){
            dict[cur]=new Node(cur->val);//存入哈希表
            cur=cur->next;
        }
        // 第二步:遍历原始链表,修改哈希表中每个新节点的next指针和random指针
        cur=head;
        while(cur){
            Node* curNewNode=dict[cur];// 获取当前节点对应的新节点
            curNewNode->next=dict[cur->next];// 修改新节点的next指针
            curNewNode->random=dict[cur->random]; // 修改新节点的random指针
            // 循环前进
            cur=cur->next;
        }
        return dict[head];
    }
};

二、链表与二叉树

剑指 Offer 36. 二叉搜索树与双向链表(中等难度)

426. 将二叉搜索树转化为排序的双向链表(中等难度)

class Solution {
private:
    Node* pre=NULL; // 当前访问节点的前一个节点
    Node* head=NULL;// 双向循环链表的头结点
public:
    Node* treeToDoublyList(Node* root) {
        if(root==NULL) return NULL;
        // 采用中序遍历的方式遍历二叉搜索树,修改为双向链表
        dfs(root);
        // 修改为循环链表
        head->left = pre;//头结点指向尾结点
        pre->right = head;//尾结点指向头结点
        return head;
    }
    // 中序遍历
    void dfs(Node* cur){
        // 终止条件
        if(cur==NULL) return;
        // 递归左节点 
        dfs(cur->left);
        // 处理节点head,pre,cur
        if(pre) pre->right=cur;// 如果pre不为空,说明双向链表上已经有节点,其指向当前节点
        else head=cur;// 如果pre为空,说明双向链表没有节点,设置头结点
        cur->left=pre;// 当前节点指向上一个
        pre=cur;// 更新上一个节点
        // 递归右节点
        dfs(cur->right);
    }
};

109. 有序链表转换二叉搜索树(中等难度)

class Solution {
public:
    // 在[left,right)获取中间节点
    ListNode* getMid(ListNode* left, ListNode* right) {
        ListNode* fast = left;
        ListNode* slow = left;
        while (fast != right && fast->next != right) {
            fast = fast->next->next;// 前进2步
            slow = slow->next;// 前进1步
        }
        return slow;
    }
    // 在[left,right)中序遍历构建二叉搜索树
    TreeNode* buildTree(ListNode* left, ListNode* right) {
        if (left == right) return nullptr;
        // 构建中间节点
        ListNode* mid = getMid(left, right);// 获取中间节点
        TreeNode* root = new TreeNode(mid->val);//构建根节点
        // 递归左右节点
        root->left =  buildTree(left, mid);
        root->right = buildTree(mid->next, right);
        return root;
    }

    TreeNode* sortedListToBST(ListNode* head) {
        return buildTree(head, nullptr);
    }
};

114. 二叉树展开为链表(中等难度)

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        // 快指针每次走2步,慢指针每次走1步,相遇即有环
        while(fast  && fast->next ) {
            slow = slow->next;
            fast = fast->next->next;
            // 快慢指针相遇,说明有环
            if (slow == fast) {
                slow=head;
                // head和相遇点相同速度出发再次相遇的就是入口
                while(fast&& slow) {
                    // 快慢指针第一次相遇,说明此时为入口
                    if (slow == fast) return slow;;
                    slow = slow->next;
                    fast = fast->next;
                }
            }
        }
        return NULL;
    }
};