代码随想录算法训练营第四天 24. 两两交换链表中的节点

本文介绍了四种链表相关的算法问题:两两交换链表中的节点,删除链表的倒数第N个节点,寻找两个链表的交点,以及检测环形链表。文中对比了不同解法,包括使用虚拟头节点、滑动窗口等技巧,并提供了详细的代码实现。这些方法加深了对链表操作的理解。

代码随想录算法训练营第四天 24. 两两交换链表中的节点

一、两两交换链表中的节点

题目链接

​ 花了点时间画图盘了一下逻辑,然后才做了出来。但是操作相对复杂一点。

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummynode = new ListNode(0);
        dummynode->next = head;
        ListNode* cur = dummynode->next;
        ListNode* temp;
        if(cur == NULL || cur->next == NULL){
            return head;
        }
        head = cur->next;
        while(cur != NULL && cur->next != NULL){
                temp = cur;
                cur = cur->next;
                dummynode->next->next = cur;
                temp->next = cur->next;
                cur->next = temp;
                cur = temp->next;
                dummynode->next = temp;
        }
        delete dummynode;
        return head;
    }
};

​ 还是Carl哥的方法通顺好理解,且后面二刷的时候容易记住。

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
        dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
        ListNode* cur = dummyHead;
        while(cur->next != nullptr && cur->next->next != nullptr) {
            ListNode* tmp = cur->next; // 记录临时节点
            ListNode* tmp1 = cur->next->next->next; // 记录临时节点

            cur->next = cur->next->next;    // 步骤一
            cur->next->next = tmp;          // 步骤二
            cur->next->next->next = tmp1;   // 步骤三

            cur = cur->next->next; // cur移动两位,准备下一轮交换
        }
        return dummyHead->next;
    }
};

二、删除链表的倒数第N个节点

题目链接
暴力解法:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        int size = 0;
        ListNode* dummnode = new ListNode(0);
        dummnode->next = head;
        ListNode* cur = dummnode;
        while(cur->next != NULL){
            cur = cur->next;
            size++;
        }
        cur = dummnode;
        for(int i =0; i<(size-n);i++){
            cur = cur->next;
        }
        ListNode* temp = cur->next;
        cur->next = cur->next->next;
        delete temp;
        head = dummnode->next;
        delete dummnode;
        return head;
    }
};

滑动窗口的思想:

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummynode = new ListNode(0);
        dummynode->next = head;
        ListNode* fast_cur = dummynode;
        ListNode* slow_cur = dummynode;
        while(fast_cur->next != NULL){
            if(n){
                fast_cur = fast_cur->next;
                n--;
            }
            else{
                fast_cur = fast_cur->next;
                slow_cur = slow_cur->next;
            }
        }
        ListNode* temp = slow_cur->next;
        slow_cur->next = slow_cur->next->next;
        delete temp;
        return dummynode->next;
    }
};

三、160.链表相交

题目链接
​ 一刷思路:算长度的差值,然后对齐

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        int sizeA = 0;
        int sizeB = 0;
        while(curA != NULL){
            curA = curA->next;
            sizeA++;
        }
        while(curB != NULL){
            curB = curB->next;
            sizeB++;
        }
        curA = headA;
        curB = headB;
        int difference = sizeA-sizeB;
        if(difference > 0){
            while(difference--){
                curA = curA->next;
            }
        }
        else if(difference < 0){
            while(difference++){
                curB = curB->next;
            }
        }
        while(curA != curB){
            curA = curA->next;
            curB = curB->next;
        }
        return curA;

    }
};

群里看到的更简洁的写法,其实思路是一样的一个是算差值,一个是相加。

​ a+c+b = b+c+a;

设交集链表长c,链表1除交集的长度为a,链表2除交集的长度为b,有

  • a + c + b = b + c + a
  • 若无交集,则a + b = b + a
class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* curA = headA;
        ListNode* curB = headB;
        while(curA != curB){
            curA = curA == NULL? headB : curA->next;
            curB = curB == NULL? headA : curB->next; 
        }   
        return curA;
    }
};

四、 142.环形链表II

题目链接
​ 这题一点思路也没有,直接看的carl的题解思路,代码实现不难。

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fastcur = head;
        ListNode* slowcur = head;
        while(fastcur != NULL && fastcur->next != NULL){
            fastcur = fastcur->next->next;
            slowcur = slowcur->next;
            if(slowcur == fastcur){
                slowcur = head;
                while(slowcur != fastcur){
                    slowcur = slowcur->next;
                    fastcur = fastcur->next;
                }
                return slowcur;
            }
        }
        return NULL;

    }
};

五、总结

​ 整体来说对链表的理解更深了一步,除了最后一题,其他的一刷能能做出来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值