D7 24. 两两交换链表中的节点 + 19. 删除链表的倒数第N个节点

24 两两交换链表中的节点(力扣:https://leetcode.cn/problems/swap-nodes-in-pairs/

条件:成对交换链表节点(而不是其中的值)剩余单数或null时退出,最后返回新head(空/单节点链表返回原head)
Tips:

  1. 由于可交换情景下需要指定原第二个节点为新头节点、空和单节点链表不需要更换头节点,所以使用虚拟头统一处理(虚拟头next指向原head且return 虚拟头next),把修改丢给后面的循环判断;
  2. 遍历指针只操作遍历和交换,所以需要定义另一个prevTail指针衔接变化后的两对节点;
  3. 交换时易混淆遍历和衔接指针的指向,建议使用first和second保证逻辑清楚,此外交换时修改的都是first或者second的next而非first本身地址,所以prevTail可以在交换后指向first不用担心地址丢失或者指向被修改的地址;
点击查看代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        //虚拟头记住未来新head的地址,不管需不需要移位,最后return dummyhead->next即可
        ListNode* dummyHead = new ListNode();
        dummyHead->next = head;
        //ListNode* dummyHead = head->next;

        //遍历用指针
        ListNode* current = head;
        //衔接切换前后两对节点
        ListNode* prevTail = dummyHead;

        //非空链表、单节点链表、后续待处理的为偶数
        while(current != nullptr && current->next != nullptr){

            ListNode* first = current;
            ListNode* second = current->next;
            ListNode* nextCurrent = current->next->next;

            //2->1
            second->next =  first;
            //1->3
            first->next = nextCurrent;

            //让上组的结尾指向新头,链接两个组
            prevTail->next = second;

            //越过12从3开始
            current = nextCurrent;
            //这里prevend更新成上一对的新尾部(第一次循环里是1)
            prevTail = first;
            
        }

        return dummyHead->next;

    }
};

19 删除链表的倒数第N个节点(力扣:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/

条件:删除倒数第n,返回head(存在空/单节点链表,但1 <= n <= 链表长度size)
Tips:

  1. 因为题目为倒数所以可能忽略了删除节点为head的情况,所以引入虚拟头;
  2. 删除倒数第(n)个所以要在它前一个停下,快指针在最后一个节点停下,所以快慢指针的gap为(n)而非(n+1),即倒数第(n-1)个节点和倒数第(1)个节点的距离;
点击查看代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode() : val(0), next(nullptr) {}
 *     ListNode(int x) : val(x), next(nullptr) {}
 *     ListNode(int x, ListNode *next) : val(x), next(next) {}
 * };
 */
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {

        //虚拟头处理要删除节点为head时的情况
        ListNode* dummy = new ListNode(0, head);
        
        ListNode* slow = dummy;
        ListNode* quick= dummy;

        int gapCount = 0;

        //移动quick指针保证和slow差距为n个节点
        while( quick->next != nullptr && gapCount < n ){
            quick = quick->next;
            gapCount++;
        }

        //差距满足后同时移动直到quick在最后、slow在倒数第n个前一个
        //空或单节点链表不会进入while,直接进行下面的删除
        while( quick->next != nullptr ){
            quick = quick->next;
            slow = slow->next;
        }

        //删除
        ListNode* toBeDelete = slow->next;
        slow->next = slow->next->next;
        delete toBeDelete;

        ListNode* newHead = dummy->next;
        delete dummy;
        return newHead;
}       
};

posted @ 2026-01-25 14:29  SCONLY  阅读(0)  评论(0)    收藏  举报