代码随想录算法训练营第四天 | 24. 两两交换链表中的节点 19.删除链表的倒数第N个节点 面试题 02.07. 链表相交 142.环形链表II

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

初见想法:迭代法或者递归

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        
        ListNode* dummyhead = new ListNode(0, head);
        ListNode* temp = dummyhead;
        while(temp->next != nullptr && temp->next->next != nullptr)
        {
            ListNode* node1 = temp->next;
            ListNode* node2 = temp->next->next;

            node1->next = node2->next;
            node2->next = node1;
            temp->next = node2;
            temp = node1;
        }

        return dummyhead->next;
    }
};

迭代法,重点还是在dummyhead, 找到需要交换的两个节点的前一个节点,然后交换两个节点,再把这个结点指向以交换节点的第一个节点

class Solution {
public:
    ListNode* swapPairs(ListNode* head) {
        
        if (head == nullptr || head->next == nullptr) return head;
        
        // 在一个swappairs中会反转两个节点,再返回新的头节点
        // swappairs里面的参数是未反转两个节点里的第一个节点
        ListNode* newhead = head->next;
        // 新的两个节点的头节点
        ListNode* temphead = swapPairs(newhead->next);

        newhead->next = head;
        // 连接此时已反转的节点和下一个已反转的节点
        head->next = temphead;

        return newhead;
    }
};

递归法,基本思想如上注释,在一个swappairs里交换,然后返回以交换节点的第一个节点

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

初见想法:双指针法,见过这题

class Solution {
public:
    ListNode* removeNthFromEnd(ListNode* head, int n) {
        if (head == nullptr || n < 0) return nullptr;

        ListNode* dummyhead = new ListNode(0, head);
        ListNode* left = dummyhead;
        ListNode* right = head;
        for (int i = 0; i < n; i++) right = right->next;

        // 使用while loop 最好不要访问next, 无法确定这个节点是否为空节点的话
        while (right)
        {
            left = left->next;
            right = right->next;
        }

        left->next = left->next->next;

        return dummyhead->next;
        
    }
};
  1. 无论是增加还是删除节点,都应该设置dummyhead,这样当有且只有一个节点的时候非常方便

  1. 倒数是从1开始的

  1. 从head算,走k步,到k+1个节点,当最后right到达空节点时, 从dummyhead算走到倒数第k-1个节点,这样就可以删除倒数第k个节点了。

Leetcode 面试题 02.07. 链表相交

初见想法:直接使用hashmap记录每个节点的地址

class Solution {
public:
    ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
        // 计算两个链表的长度
        ListNode *currA = headA, *currB = headB;
        int lenA = 0, lenB = 0;

        while (currA)
        {
            currA = currA->next;
            lenA++;
        }

        while (currB)
        {
            currB = currB->next;
            lenB++;
        }

        currA = headA;
        currB = headB;

        if (lenB > lenA)
        {
            swap(lenA, lenB);
            swap(currA, currB);
        }

        int gap = lenA - lenB;
        for (int i = 0; i < gap; i++) currA = currA->next;

        while (currA != nullptr)
        {
            if (currA == currB) return currA;

            currA = currA->next;
            currB = currB->next;
        }

        return nullptr;
    }
};

先让长的链表走到和短的链表一样的位置,然后再一起往后,如果存在两个节点出现一样的情况,则链表相交

Leetcode 142.环形链表II

环形链表,卡哥视频推导:here

class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *fast = head, *slow = head;
        while (fast != nullptr && fast->next != nullptr)
        {
            // 快慢节点会在环形链表中相遇
            fast = fast->next->next;
            slow = slow->next;

            if (fast == slow)
            {
                ListNode* index1 = head;
                ListNode* index2 = fast;
                
                while (index1 != index2)
                {
                    index1 = index1->next;
                    index2 = index2->next;
                }

                return index1;
            }
        }

        // fast跑到空指针处,那么链表不是环形指针
        return nullptr;
    }
};

  1. 快慢指针判断是否有环,当进入环以后,快指针每次走两步,慢指针每次走一步,快指针在以每次1个节点的速度接近慢指针,也就是说,快指针一定会追上慢指针

  1. 当slow进入环时, 假设fast和slow的距离为n,fast差slown步,那么只要slow再走n步,那么slow一定被fast追上,而n是一定小于环的长度的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值