随想录一刷Day04——链表

Day04_链表

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

24. 两两交换链表中的节点
思路:

按照下如图模拟
在这里插入图片描述

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        ListNode* _dummyHead = new ListNode(0);
        _dummyHead->next = head;
        ListNode* cur = _dummyHead;
        while (cur->next && cur->next->next) {
            ListNode* tmp = cur->next; // 记录节点1
            ListNode* tmp_next_pair = cur->next->next->next; // 记录下一对节点的起点
            cur->next = cur->next->next; // 步骤一
            cur->next->next = tmp; // 步骤二
            tmp->next = tmp_next_pair; // 步骤三
            cur = cur->next->next; // 虚拟节点移动到下对节点的正确位置
        }
        return _dummyHead->next;
    }
};

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

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

本来想两次遍历,看到卡哥的双指针,直呼挺妙,虽然复杂度也是 O ( n ) O(n) O(n)
利用双指针间格n个位置,就可以在fast指针移动到链表结尾时,slow指针停在要删除的节点前。

在这里插入图片描述

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        ListNode* _dummyHead = new ListNode(0);
        _dummyHead->next = head;
        ListNode* fast_index = _dummyHead;
        ListNode* slow_index = _dummyHead;
        while(n-- && fast_index) {
            fast_index = fast_index->next;
        }
        while(fast_index->next) {
            fast_index = fast_index->next;
            slow_index = slow_index->next;
        }
        slow_index->next = slow_index->next->next;
        return _dummyHead->next;
    }
};

7. 链表相交

面试题 02.07. 链表相交
思路:

又不是自己想的,呜呜呜
显然不能是利用两个节点的值相等作为判断依据,要判断指针地址一致才行。如何让两个节点能够在相交处相遇呢?就让两个链表从头部对齐变为尾部对齐,接下来一起以相同的速度往后遍历,一定会在相交的点处相遇。

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        ListNode* A_pos = headA;
        ListNode* B_pos = headB;
        int lenA = 0, lenB = 0;
        while(A_pos) { // 获取A链表的长度
            lenA++;
            A_pos = A_pos->next;
        }
        while(B_pos) { // 获取B链表的长度
            lenB++;
            B_pos = B_pos->next;
        }

        int delta_len = lenA - lenB; // 默认链表A长
        A_pos = headA;
        B_pos = headB;
        if (delta_len < 0) { // 调整为A链表为长链表
            swap(lenA, lenB);
            swap(A_pos, B_pos);
            delta_len = abs(delta_len);
        }
        
        while(delta_len--) { // 将A、B链表尾部对齐
            A_pos = A_pos->next;
        }

        while (A_pos && A_pos != B_pos) { // 同时遍历A、B链表,找到相交节点
            A_pos = A_pos->next;
            B_pos = B_pos->next;
        }

        return A_pos;
    }
};

8. 环形链表 II

142. 环形链表 II
思路:

实用两个指针,一快一慢,快指针一次走两步,慢指针一次走一步。如果两个指针相交,则有环。然后快指针在交点处,慢指针在起点处,以步长为1运动,直到相遇点,为环的交点。

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode* fast_index = head;
        ListNode* slow_index = head;
        while(fast_index && slow_index) {
            fast_index = fast_index->next;
            slow_index = slow_index->next;
            if (fast_index == NULL || slow_index == NULL) return NULL;
            fast_index = fast_index->next;
            if (fast_index == slow_index) break;
        }
        if (fast_index == NULL || slow_index ==NULL) return NULL;
        // cout << "here" << endl;
        slow_index = head;
        while (fast_index != slow_index) {
            fast_index = fast_index->next;
            slow_index = slow_index->next;
        }
        return fast_index;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值