【代码随想录37期】Day04 两两交换链表中的节点、删除链表的倒数第N个节点、链表相交、环形链表II

#打卡记录

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

按图中这个顺序做,很清晰,很省脑子,记录一下

关于虚拟头结点,这个是为了统一处理操作,正常移除操作时,头节点的操作和其他节点的不一致,引入虚拟头节点后可统一操作。代码表示:ListNode* ans = new ListNode(0, head);

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        if(head == nullptr) return nullptr;
        int temp = 0;
        int flag = 0;
        ListNode* ans = new ListNode(0, head);
        ListNode* cur = ans;
        while(cur->next != nullptr && cur->next->next != nullptr){
            ListNode* temp1 = cur->next;
            ListNode* temp2 = cur->next->next->next;
            
            cur->next = temp1->next;
            cur->next->next = temp1;
            cur->next->next->next = temp2;

            cur = cur->next->next;
        }
        return ans->next;
    }
};

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

双指针的经典应用,如果要删除倒数第n个节点,让fast移动n步,然后让fast和slow同时移动,直到fast指向链表末尾。删掉slow所指向的节点就可以了。

由于使用了虚拟头节点,所以操作需要变成fast先移动n+1步。

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* ans = new ListNode(0, head);
        ListNode* fast = ans;
        ListNode* slow = ans;
        while(n != 0 && fast->next != nullptr){
            fast = fast->next;
            n--;
        }
        fast = fast->next;
        while(fast != nullptr){
            fast = fast->next;
            slow = slow->next;
        }
        ListNode* node = slow->next;
        slow->next = slow->next->next;
        delete node;

        return ans->next;
    }
};

面试题 02.07. 链表相交

A,B链表假设相交,则可分割为a+c和b+c,c为相交后的部分,则可得出等式

a+c+b = b+c+a,即走完A链表再走B链表单独的部分的路程,和走完B链表再走A链表单独的部分的路程是相等的。

假设不相交,则a+b = b+a,两根指针在遍历完A,B链表后,会同时位于链表的末尾——null的位置。

所以可以得出以下代码。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* cur1 = headA;
        ListNode* cur2 = headB;
        while(cur1 != cur2){
            if(cur1 == NULL){
                cur1 = headB;
            }
            else{
                cur1 = cur1->next;
            }
            if(cur2 == NULL){
                cur2 = headA;
            }
            else{
                cur2 = cur2->next;
            }
        }
        return cur1;
    }
};

142.环形链表II

同样是快慢指针,但这里需要注意fast和slow之间差的“速度”是多少,因为数据是离散的,不能完全按照跑道套圈来理解,如果速度差设置的不对可能导致两者无法相遇,目前已知fast一次走两格,slow一次走一格,

fast = fast->next->next;
slow = slow->next;

这个速度差是可行的。

找到入口的方法:从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        ListNode* start = head;
        do{
            if(fast == NULL || fast->next == NULL){
                return NULL;
            }
            fast = fast->next->next;
            slow = slow->next;
        }while(fast != slow);

        while(slow != start){
            slow = slow->next;
            start = start->next;
        }
        return start;
    }
};

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值