[TOC]

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

一、链表相交的LeetCode题目

1、找到2个单链表的相交点

160. 相交链表(简单难度)

面试题 02.07. 链表相交(简单难度)

剑指 Offer 52. 两个链表的第一个公共节点(简单难度)

剑指 Offer II 023. 两个链表的第一个重合节点(简单难度)

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode *pA=headA;
        ListNode *pB=headB;
        // 获取两个单链表的长度
        int lenA=0;
        int lenB=0;
        while(pA){
            lenA++;
            pA=pA->next;
        }
        while(pB){
            lenB++;
            pB=pB->next;
        }
        // 让长链表的遍历指针先走
        pA=headA;
        pB=headB;
        if(lenA>lenB){
            int gap=lenA-lenB;
            while(gap--){
                pA=pA->next;
            }
        }
        else if(lenA<lenB){
            int gap=lenB-lenA;
            while(gap--){
                pB=pB->next;
            }
        }
        //长短链表同时开始走
        while(pA&&pB){
            if(pA==pB) return pA;
            pA=pA->next;
            pB=pB->next;
        }
        return NULL;
    }
};

2、环形链表

876. 链表的中间结点(简单难度)

class Solution {
public:
    ListNode* middleNode(ListNode* head) {
        // 方法一:快慢指针
        // ListNode* slow=head;
        // ListNode* fast=head;
        // while(slow&&fast&&fast->next){
        //     slow=slow->next;//2,3,4
        //     fast=fast->next->next;//3,5,null
        // }
        // return slow;
        // 方法二:计数法
        int len=0;
        ListNode* p=head;
        if(p==nullptr) return nullptr;
        while(p){
            p=p->next;
            len++;
        }
        // 
        int i=0;
        p=head;
        while(p&&i<len/2){
            p=p->next;
            i++;
        }
        return p;
    }
};

141. 环形链表(简单难度)

class Solution {
public:
    bool hasCycle(ListNode *head) {
        // 快慢指针
        ListNode *fast=head;
        ListNode *slow=head;
        while(fast  && fast->next){
            slow=slow->next;
            fast=fast->next->next;
            if(slow==fast) return true; //指针相同说明相遇
        }
        return false;
    }
};

142. 环形链表 II(中等难度)

剑指 Offer II 022. 链表中环的入口节点(中等难度)

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;
    }
};

二、链表合并的LeetCode题目

1、合并有序链表

21. 合并两个有序链表(简单难度)

剑指 Offer 25. 合并两个排序的链表(简单难度)

class Solution {
public:
    ListNode* mergeTwoLists(ListNode* list1, ListNode* list2) {
        ListNode* result = new ListNode(-1); // 结果链表,默认第一个为虚拟头结点
        ListNode* p = result;// 遍历指针,该指针会变化
        // 同时遍历两2个链表
        while(list1&&list2){
            // 谁小将谁添加进结果链表
            if(list1->val<=list2->val){
                p->next=list1;
                list1=list1->next;
            }
            else{
                p->next=list2;
                list2=list2->next;
            }
            p=p->next;
        }
        // 此时有个链表有剩余,继续添加
        while(list1!=NULL){
            p->next=list1;
            list1=list1->next;
            p=p->next;
        }
        while(list2!=NULL){
            p->next=list2;
            list2=list2->next;
            p=p->next;
        }
        return result->next;
    }
};

2、拼接链表

1669. 合并两个链表(中等难度)

class Solution {
public:
    ListNode* mergeInBetween(ListNode* list1, int a, int b, ListNode* list2) {
        // 找到list1的第a-1个节点
        int i=0;
        ListNode* pa=list1;
        while(pa&&i<a-1){
            pa=pa->next;
            i++;
        }
        // 找到list1的第b个节点;
        i=0;
        ListNode* pb=list1;
        while(pb&&i<b){
            pb=pb->next;
            i++;
        }
        // 找到list2的最后一个节点
        ListNode* last=list2;
        while(last->next){
            last=last->next;
        }
        // 拼接两个链表
        pa->next=list2;
        last->next=pb->next;
        return list1;
    }
};