代码随想录刷题 | Day4

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 今日学习目标
  • 一、算法题
    • 1.两两交换链表中的节点
    • 2.删除链表的倒数第N个节点
    • 3.链表相交
    • 4.环形链表 II
  • 学习心得
  • 学习及参考内容


今日学习目标

两两交换链表中的节点(24)
删除链表的倒数第N个节点(19)
链表相交(160)
环形链表II(142)

一、算法题

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

题目:给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
思路:单链表的处理中,前一个节点是比较重要的,所以本题采用虚拟头节点,就不需要单独处理头节点了。指针指向虚拟头节点,设置一个临时节点temp记录第一个节点。
1.cur->next指向第二个节点。
2.temp->next指向第三个节点。
3.将第二个节点指向temp,cur指针移动两位,做下一轮交换。
代码随想录刷题 | Day4_第1张图片

/**
 * 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();
        dummyNode->next = head;
        ListNode* cur = dummyNode;
        while(cur->next != nullptr && cur->next->next != nullptr) {
            ListNode* temp = cur->next;
            cur->next = cur->next->next;
            temp->next = cur->next->next;
            cur->next->next = temp;
            cur = cur->next->next;
        }
        return dummyNode->next;
    }
} 

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

题目:给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
思路:本题采用的是双指针的思路,删除倒数第n个结点,让slow指向倒数第n个结点的前一个结点,先让fast移动n+1步,然后让fast和slow同时移动,当fast指向最后结点时,slow刚好指向需要删除结点的前一个结点。考虑到删除头结点的情况,构造一个虚拟头结点更方便操作。

/**
 * 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* dummyNode = new ListNode(0);
        dummyNode->next = head;
        //定义快慢指针
        ListNode* fast = head;
        ListNode* slow = dummyNode;
        //保存要删除的节点
        ListNode* cur = nullptr;
        //快指针先走n+1
        while (fast&&n--) {
            fast = fast->next;
	    }
        while(fast != NULL) {
            fast = fast->next;
            slow = slow->next;
        }
        cur = slow->next;
        slow->next = cur->next;
        delete cur;
        return dummyNode->next;
    }
};

总结:需要注意对链表操作后不可直接返回head结点,需要考虑到删除第一个结点的情况。

3.链表相交

题目:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

图示两个链表在节点 c1 开始相交:
代码随想录刷题 | Day4_第2张图片
题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。
思路:求出两个链表的长度差size,长的链表先移动size,两个链表同时移动,判断相同节点。

/**
 * 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) {
        int sizeA = 0;
        int sizeB = 0;
        ListNode* pointerA = headA;
        ListNode* pointerB = headB;
        while(pointerA->next != NULL) {
            pointerA = pointerA->next;
            sizeA++;
        }
        while(pointerB->next != NULL) {
            pointerB = pointerB->next;
            sizeB++;
        }
        pointerA = headA;
        pointerB = headB;
        if(sizeB > sizeA) {
            swap(sizeA, sizeB);
            swap(pointerA, pointerB);
        }
        int size = sizeA - sizeB;
        while(size--) {
            pointerA = pointerA->next;
        }
        while(headA != NULL) {
            if(pointerA == pointerB) {
                return pointerA;
            }
            pointerA = pointerA->next;
            pointerB = pointerB->next;
        }
        return NULL;
    }
};

4.环形链表 II

题目:给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。

思路:双指针,快指针每次走两个节点,慢指针每次走一个节点,如果有环,快慢指针就会相遇。

/**
 * 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) {
            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 index2;
            }
        }
        return NULL;
    }
};

总结:判断出是否有索引后,还需要返回索引的位置。


学习心得

今日卡住的地方在于只能判断出一部分的内容,有思路但不多,还需要加强练习。

学习及参考内容

代码随想录

你可能感兴趣的:(代码随想录练习,笔记,算法)