24 交换节点 | 19 删除倒N节点 | 160 链表相交

642 阅读3分钟

24 交换节点

题目描述:给定一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。

要求:不修改节点内部的值。

思路

参考:www.bilibili.com/video/BV1YT…

截屏2023-01-16 21.14.17.png

截屏2023-01-16 21.15.05.png

截屏2023-01-16 21.14.46.png

截屏2023-01-16 21.15.18.png

代码

 /**
  * 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) {
        ListNode* dummyNode = new ListNode(-1, head);
        ListNode* cur = dummyNode;  // cur:交换cur->next和cur->next->next
        while (cur->next != NULL && cur->next->next != NULL)
        {
             ListNode* temp1 = cur->next;        // 保存要交换的第一个节点
             ListNode* temp2 = cur->next->next->next;  // 保存要交换的第二个节点的下一个节点,即第三个节点
             cur->next = cur->next->next;  // 让cur的next指向原链表第二个指针
             cur->next->next = temp1;      // 让原链表第二个节点的next指向第一个节点
             cur->next->next->next = temp2; // 让原链表第一个节点的next指向第三个节点
 ​
             cur = cur->next->next;    // 让cur指向原链表的第一个节点,为下次做准备
         }
         return dummyNode->next; 
     }
 };

19 删除倒N节点

题目描述:给定一个链表,删除链表的倒数第 n 个节点,并返回链表的头节点。

思路

本题比较简单,通过快慢指针解决。让快指针先走 n 步,之后让快指针和慢指针一起走,当快指针走到最后一个节点时,慢指针恰好走到要删除节点的前一个节点。

代码

 /**
  * 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) {
         ListNode* dummyHead = new ListNode(-1, head);
         ListNode* fast = dummyHead;
         ListNode* slow = dummyHead;
         for (int i = 0; i < n; i++)
             fast = fast->next;
         while (fast->next != NULL)
         {
             fast = fast->next;
             slow = slow->next;
         }
         slow->next = slow->next->next;
         return dummyHead->next;
     }
 };

160 链表相交

题目描述:给定两个单链表的头节点 headA 和 headB,找出并返回两个单链表相交的起始节点。如果两个链表不相交,返回 NULL。

思路

参考:leetcode.cn/problems/in…

第一次做的话会比较难想,不过,一旦知道了这种做法,以后就很难忘记。

核心在于,让两个p指针分别指向链表头,然后依次遍历对应链表,直至遇到空指针,让遇到空指针的p指向另一条链表的头节点,然后继续继续遍历(两条链表一起),直至另一个p指针遇到空指针,然后让其指向另一条链表的头节点,再继续遍历,判断p1和p2是否指向同一个节点,如果是,该节点即使相交节点;遍历至p1为空或p2为空,说明没有相交节点。

代码

 /**
  * Definition for singly-linked list.
  * struct ListNode {
  *     int val;
  *     ListNode *next;
  *     ListNode(int x) : val(x), next(NULL) {}
  * };
  */
 class Solution {
 public:
     ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
         ListNode* p1 = headA;
         ListNode* p2 = headB;
         while (p1 != NULL && p2 != NULL)
         {
             p1 = p1->next; 
             p2 = p2->next;
         }
         if (p1 == NULL)
         {
             p1 = headB;
             while (p2 != NULL)
             {
                 p1 = p1->next; 
                 p2 = p2->next;
             }
             p2 = headA;
             while (p1 != NULL || p2 != NULL)
             {
                 if (p1 == p2)
                     return p1;
                 p1 = p1->next;
                 p2 = p2->next;
             }
         }
         else
         {
             p2 = headA;
             while (p1 != NULL)
             {
                 p1 = p1->next; 
                 p2 = p2->next;
             }
             p1 = headB;
             while (p1 != NULL || p2 != NULL)
             {
                 if (p1 == p2)
                     return p1;
                 p1 = p1->next; 
                 p2 = p2->next;
             }
         }
         return NULL;
     }
 };