代码随想录Day4链表02

  1. 两两交换链表中的节点
    https://leetcode.cn/problems/swap-nodes-in-pairs/
    首先,当需要对链表进行增删改这样的操作都应该引入虚拟节点,这样可以省去对头节点的特殊处理;其次,cur节点每一次执行交换后都应该直接指向下一个交换后的头节点,因为这样才能够将三个节点都联系起来,用tmp1,tmp2指针进行存储,最终完成交换。
点击查看代码
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(0, head);
    ListNode *cur = dummyNode;

    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;
      tmp->next = tmp1;
      cur = cur->next->next;
    }

    ListNode *result = dummyNode->next;
    delete dummyNode;
    return result;
  }
};
  1. 删除链表的倒数第n个节点
    https://leetcode.cn/problems/remove-nth-node-from-end-of-list/
    首先,拿到这个题目的一般思路就是先遍历一遍知道链表的总长度,在遍历一遍根据总长度去删除第n个节点,时间复杂度也不高,每个元素都至多被遍历两次,是一个好的思路,但是使用快慢指针无疑是对前面学习的学以致用,一般来说这种需要循环两次的题目都值得用双指针的思路去重构;对于双指针的算法来说,可以让fast指针先出发n+1步,因为删除第n个节点必然是要让第n-1个节点去删除,因为这只是一个简单链表。下面的图或许更加清晰。
    截图 2025-07-12 15-38-19
点击查看代码
class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* dummyHead = new ListNode(0);
        dummyHead->next = head;
        ListNode* slow = dummyHead;
        ListNode* fast = dummyHead;
        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; 
        
        // ListNode *tmp = slow->next;  C++释放内存的逻辑
        // slow->next = tmp->next;
        // delete tmp;
        
        return dummyHead->next;
    }
};

  1. 链表相交
    https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/
    本题的思路不难,首先是要将两个链表的末端对齐,之后再同时从头节点出发,看看是否有相同的节点,即可判断是否相交。PS:swap函数感觉可以特别记忆一下。
点击查看代码
using namespace std;

struct ListNode {
  int val;
  ListNode *next;
  ListNode(int x) : val(x), next(nullptr) {}
};

class Solution {
public:
  ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
    ListNode *curA = headA;
    ListNode *curB = headB;

    // 由于是单链表,先统计每个链表的长度
    int lenA = 0;
    int lenB = 0;

    while (curA != nullptr) {
      lenA++;
      curA = curA->next;
    }

    while (curB != nullptr) {
      lenB++;
      curB = curB->next;
    }

    curA = headA;
    curB = headB;

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

    int gap = lenA - lenB;

    while (gap--) {
      curA = curA->next;
    }

    while (curA != nullptr && curB != nullptr) {
      if (curA == curB) {
        return curA;
      } else {
        curA = curA->next;
        curB = curB->next;
      }
    }

    return nullptr;
  }
};
  1. 环形链表
    https://leetcode.cn/problems/linked-list-cycle-ii/
    首先,我们要判断这个链表是否有环,可以设置一个快指针,一个慢指针,fast每次走2个节点,slow每次走1个,为什么要这样呢,因为这样可以fast会以每次一个节点的速度在环内赶上slow,如果速度是3的话,很有可能过快导致直接超越slow使用更多的时间才能检测出来;其次,就是数学部分的推导,这里就不再赘述,代码随想录网站肯定比我讲的好https://programmercarl.com/0142.%E7%8E%AF%E5%BD%A2%E9%93%BE%E8%A1%A8II.html#%E6%80%9D%E8%B7%AF
点击查看代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast = head;
        ListNode* slow = head;
        while(fast != NULL && fast->next != NULL) {
            slow = slow->next;
            fast = fast->next->next;
            // 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇
            if (slow == fast) {
                ListNode* index1 = fast;
                ListNode* index2 = head;
                while (index1 != index2) {
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index2; // 返回环的入口
            }
        }
        return NULL;
    }
};

posted @ 2025-07-12 15:52  YZranger  阅读(52)  评论(0)    收藏  举报