代码随想录算法训练营第四天|24两两交换链表中的结点、19删除链表的倒数第N个结点、面试题02.07.链表相交、142环形链表

文章讲述了如何解决LeetCode中的链表题目,包括两两交换链表节点、删除倒数第N个节点、查找链表相交以及检测环形链表的方法,强调了使用虚拟头结点和快慢指针策略的重要性。
摘要由CSDN通过智能技术生成

leetcode24两两交换链表中的结点

我的思路见图,一开始没有设置虚拟头结点,画图画了几遍,发现还是要设置一个虚拟头结点,另外,最后返回的不能是head,因为此时head已经不在链表首位,而是变成了链表第二位。

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* cur = head;
        ListNode* tmp;
        ListNode* pre = new ListNode(0);
        pre->next = cur;
        ListNode* q = pre;
        while(cur && cur->next){
            pre->next = cur->next;
            tmp = cur->next->next;
            cur->next->next = cur;
            cur->next = tmp;
            pre = cur;
            cur = tmp;
        }
        head = q->next;
        delete q;
        return head;
    }
};

看了卡尔哥的解析,还是解析的图和代码更简洁直观,也更有逻辑,特别是要学学怎么好好画图,感觉图画得好,思路也更清晰

leetcode19删除列表的倒数第N个结点

这一题我一开始用的笨方法先遍历链表得到链表的长度,然后找倒数第N个,很麻烦而且明显这不是考察的意图。

正确方法是设置两个指针,一个快指针一个慢指针,快指针在慢指针后面的n+1步。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyhead = new ListNode(0);
        dummyhead->next = head;
        ListNode* slow = dummyhead;
        ListNode* fast = dummyhead;
        for(int i = 0; i < n; i++){
            fast = fast->next;
        }
        while(fast->next){
            fast = fast->next;
            slow = slow->next;
        }
        ListNode* q = slow->next;
        slow->next = slow->next->next;
        delete q;

        return dummyhead->next; // 最后千万不要返回head,因为head可能被删除了
    }
};

解析里是这样的,实际上是让fast移动到带虚拟头结点的第n+2位,原链表的第n+1位,当fast移动到null时,slow正好在倒数n+1位

while表达式是先判断n,再自减

while(n-- && fast != NULL) {
            fast = fast->next;
        }
        fast = fast->next; // fast再提前走一步,因为需要让slow指向删除节点的上一个节点
        while (fast != NULL) {
            fast = fast->next;
            slow = slow->next;
        }
        slow->next = slow->next->next; 

面试题02.07链表相交

这一题通过看图可以观察出规律,求出两个链表的长度并求出差值,假设A比B长, 让指针A移动到和指针B末尾对齐,也就是让A指向链表的长度和B相同,A和B同时向后移动,比较A和B是否,相同的位置就是相交的位置。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        int nA = 0;
        int nB = 0;
        int n;
        ListNode* tmpA = headA;
        ListNode* tmpB = headB;
        while(tmpA){
            nA++;
            tmpA = tmpA->next;
        }
        while(tmpB){
            nB++;
            tmpB = tmpB->next;
        }
        tmpA = headA;
        tmpB = headB;
        if(nA >= nB){
            n = nA - nB;
            while(n--){
                tmpA = tmpA->next;
            }
            while(tmpB && tmpA != tmpB){ // 首先要保证短的那一个不是null
                tmpA = tmpA->next;
                tmpB = tmpB->next;
            }
            return tmpB; // 返回短的那一个,即使没有交点,最后也能返回null
        }
        else{
            n = nB - nA;
            while(n--){
                tmpB = tmpB->next;
            }
            while(tmpA != tmpB){
                tmpA = tmpA->next;
                tmpB = tmpB->next;
            }
            return tmpA;
        }

    }
};

解析为了让curA始终指向长的那个链表,是这样的

 if (lenB > lenA) {
            swap (lenA, lenB);
            swap (curA, curB);
        }

leetcode142环形链表

fast走两步,slow走一步,最后fast和slow会在环内相遇

证明如下:

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast && fast->next){ // 即使只有一个结点,如果有环,就不可能存在空指针
            fast = fast->next->next;
            slow = slow->next;
            if(fast == slow){
                ListNode* index1 = fast;
                ListNode* index2 = head;
                while(index1 != index2){
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index2;
            } 
        }
        return NULL;
    }
};

  • 8
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值