Day4 链表 LeetCode 24 19 142

72 阅读3分钟

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

心得

  • 虚拟头指针好用,在于统一化操作,交换只要按照题意即可,但是要考虑如何保存当前的位置,此时需要引入临时变量,同时针对奇偶情况进行讨论,是否能纳入统一框架类
  • 需要注意空指针报错,&&的特性,保证第一个false不会执行第二个,同时注意返回的方式
  • 按照左右顺序逐个对调即可,对调前后某些结点指针发生变化无法找到之前位置,这也是提供临时变量的原因

题解

/**
 * 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* dummyHead = new ListNode();
        dummyHead->next = head; 
        ListNode* cur = dummyHead;
        while (cur->next != nullptr && cur->next->next != nullptr){
            ListNode* temp = cur->next; // 需要保存
            ListNode* temp1 = cur->next->next->next;

            cur->next = cur->next->next;
            cur->next->next = temp;
            cur->next->next->next = temp1;
            cur = cur->next->next;
        }
        return dummyHead->next;

    }
};

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

心得

  • 双指针法,倒数第N个说明两个指针间隔n个,所以一次遍历的话,slow指向删除位置
  • 但是要操作删除位置必须知道其前面一个位置,所以fast需要多走一步

题解

/**
 * 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(0);
        dummyHead->next = head;
        ListNode* slow = dummyHead;
        ListNode* fast = dummyHead;
        while (n-- && fast != nullptr){
            fast = fast->next;
        }
        fast = fast->next;
        while (fast != nullptr){
            fast = fast->next;
            slow = slow->next;
        }
        ListNode* temp = slow->next;
        slow->next = slow->next->next;
        delete temp;

        return dummyHead->next;

    }
};

面试题 02.07. 链表相交

心得

  • 拉平同一长度,开始遍历看看何时等,技巧性

题解

  • 时间复杂度O(m+n)
  • 空间复杂度O(1)
/**
 * 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* curA = headA;
        ListNode* curB = headB;
        int m = 0;
        int n = 0;
        if (curA == nullptr || curB == nullptr) return nullptr;
        while (curA != nullptr){
            curA = curA->next;
            m++;
        }
        while (curB != nullptr){
            curB = curB->next;
            n++;
        }
        curA = headA;
        curB = headB;
        int delta = m > n? m-n : n - m;
        if (m > n){
            while (delta--){
                curA = curA->next;
            }
        } else {
            while (delta--){
                curB = curB->next;
            }
        }
        int minVaue = m > n ? n : m;
        while (minVaue--){
            if (curA == curB) return {
                curA;
            }
            curA = curA->next;
            curB = curB->next;
        }
        return nullptr;
        
    }
};

142. 环形链表 II

心得

  • 对于环的理解不足,可以类比操场跑圈,速度快慢的相遇问题,抽象出来类似解法

题解

  • 双指针法,重点在于如何理解或者证明有环,快慢指针,如果无环,不可能相遇,如果有换必相遇(分别速度2和1,间隔1,相对速度1,必然相遇)
  • 其次考虑索引位置,考虑特殊情况时,两者同速度
/**
 * 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 != nullptr&& fast->next != nullptr){
            fast = fast->next->next;
            slow = slow->next;
            if (fast == slow){
                ListNode* index1 = fast;
                ListNode* index2 = head;
                while (index1 != index2){
                    index1 = index1->next;
                    index2 = index2->next;
                }
                return index1;
            }
        }

        return nullptr;
        
    }
};