五道超经典题目,带你手撕链表题(多种方法实现)上

简介: 五道超经典题目,带你手撕链表题(多种方法实现)

🌺237. 删除链表中的节点


🍁题目描述


请编写一个函数,用于 删除单链表中某个特定节点 。在设计函数时需要注意,你无法访问链表的头节点 head ,只能直接访问 要被删除的节点 。


题目数据保证需要删除的节点 不是末尾节点 。


示例 1:


f662425b6386b7f1fc88dc35dc2c58ea_40c0c44a01894435ba6ff3d158a7c95f.png


输入:head = [4,5,1,9], node = 5

输出:[4,1,9]

解释:指定链表中值为 5 的第二个节点,那么在调用了你的函数之后,该链表应变为 4 -> 1 -> 9


示例 2:


b380990590bd922530ae215de4498fed_17aadd5a58d14c0d92833ba4f0e8aaf7.png


输入:head = [4,5,1,9], node = 1

输出:[4,5,9]

解释:指定链表中值为 1 的第三个节点,那么在调用了你的函数之后,该链表应变为 4 -> 5 -> 9


提示:


   链表中节点的数目范围是 [2, 1000]

   -1000 <= Node.val <= 1000

   链表中每个节点的值都是 唯一 的

   需要删除的节点 node 是 链表中的节点 ,且 不是末尾节点


🍁基础框架


C++ 版本给出的基础框架代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
    }
};


🍁详细思路


🍀思路一


由于不能访问给定的要删除的结点前一结点,不能采用常见的删除方法。


根据题目提示,要删除的结点不是末尾结点,我们可以对删除结点的下一结点进行操作。


将删除结点后面一个点的值交换到删除节点

将删除节点指向删除节点后面一个点的后面一个点。

77c17b45ca5bb5ce265ea78abfe70caa_df8fdb5675cf4f39b65367428bfc1bb8.png


💬 代码演示


/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    void deleteNode(ListNode* node) {
        node->val = node->next->val;
        node->next = node->next->next;
    }
};


🌺876. 链表的中间结点


🍁题目描述


给定一个头结点为 head 的非空单链表,返回链表的中间结点。


如果有两个中间结点,则返回第二个中间结点。


示例 1:


输入:[1,2,3,4,5]

输出:此列表中的结点 3 (序列化形式:[3,4,5])

返回的结点值为 3 。 (测评系统对该结点序列化表述是 [3,4,5])。

注意,我们返回了一个 ListNode 类型的对象 ans,这样:

ans.val = 3, ans.next.val = 4, ans.next.next.val = 5, 以及 ans.next.next.next = NULL.


示例 2:


输入:[1,2,3,4,5,6]

输出:此列表中的结点 4 (序列化形式:[4,5,6])

由于该列表有两个中间结点,值分别为 3 和 4,我们返回第二个结点。


提示:


   给定链表的结点数介于 1 和 100 之间。


🍁基础框架


C++ 版本给出的基础框架代码如下:

/**
 * 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* middleNode(ListNode* head) {
    }
};


🍁详细思路


🍀思路一【数组】


遍历链表,将链表内元素存入数组。若数组长度为 A ,则中间结点为 A/2


💬 代码演示


/**
 * 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* middleNode(ListNode* head) {
        vector<ListNode*> A = {head};
        while (A.back()->next != NULL)
            A.push_back(A.back()->next);
        return A[A.size() / 2];
    }
};


🍀思路二【快慢指针】


使用快慢指针,快指针一次走两步,满指针一次走一步。当快指针移动到链表的末尾时,慢指针恰好到链表的中间。


💬 代码演示


/**
 * 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* middleNode(ListNode* head) {
        ListNode* slow = head;
        ListNode* fast = head;
        while (fast != NULL && fast->next != NULL) {
            slow = slow->next;
            fast = fast->next->next;
        }
        return slow;
    }
};


🌺剑指 Offer 24. 反转链表


🍁题目描述


定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。


示例:


输入: 1->2->3->4->5->NULL

输出: 5->4->3->2->1->NULL


限制:


0 <= 节点个数 <= 5000


🍁基础框架


C++ 版本给出的基础框架代码如下:

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* reverseList(ListNode* head) {
    }
};


🍁详细思路


🍀思路一【迭代】


翻转链表只需要把每一个指针的指向反过来就行了,我们定义两个指针,一个指向前一结点,另一个指向当前结点,然后进行反向操作即可。


💬 代码演示


/**
 * 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* reverseList(ListNode* head) {
        ListNode* prev = nullptr;
        ListNode* curr = head;
        while (curr) {
            ListNode* next = curr->next;
            curr->next = prev;
            prev = curr;
            curr = next;
        }
        return prev;
    }
};


🍀思路二【递归】


递归三部曲


递归结束条件,

找到函数的等价关系式

调用函数

(1)当头结点或第二个结点为空的时候,返回头结点


(2)在返回的过程中,让当前结点的下一个结点的next指向当前结点,当前结点的next指向NULL,实现局部翻转。


(3)调用函数


💬 代码演示


/**
 * 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* reverseList(ListNode* head) {
        if (!head || !head->next) 
        {
            return head;
        }
        ListNode* newHead = reverseList(head->next);
        head->next->next = head;
        head->next = nullptr;
        return newHead;
    }
};

相关文章
|
6月前
【LeetCode题目详解】(三)21.合并两个有序链表、141.环形链表、142.环形链表Ⅱ
【LeetCode题目详解】(三)21.合并两个有序链表、141.环形链表、142.环形链表Ⅱ
76 0
|
6月前
|
测试技术
【LeetCode题目详解】(二)206.反转链表、876.链表的中间结点
【LeetCode题目详解】(二)206.反转链表、876.链表的中间结点
46 0
数据结构:链表的一些经典的OJ题目,环形链表问题
数据结构:链表的一些经典的OJ题目,环形链表问题
|
9月前
链表OJ题目1 (移除链表元素)
力扣(链接放这里喽)
36 0
|
5天前
|
算法 容器
class034 链表高频题目和必备技巧【算法】
class034 链表高频题目和必备技巧【算法】
35 0
class034 链表高频题目和必备技巧【算法】
|
6月前
链表经典题目(上)以及双向链表的增删改查
链表经典题目(上)以及双向链表的增删改查
|
7月前
|
存储 算法 Java
算法宝典1——Java版本(此系列持续更新,这篇文章有20道)(有题目的跳转链接)(此份宝典包含了链表、栈、队列、二叉树的算法题)(下)
算法宝典1——Java版本(此系列持续更新,这篇文章有20道)(有题目的跳转链接)(此份宝典包含了链表、栈、队列、二叉树的算法题)(下)
|
7月前
|
算法 Java 索引
算法宝典1——Java版本(此系列持续更新,这篇文章有20道)(有题目的跳转链接)(此份宝典包含了链表、栈、队列、二叉树的算法题)(上)
算法宝典1——Java版本(此系列持续更新,这篇文章有20道)(有题目的跳转链接)(此份宝典包含了链表、栈、队列、二叉树的算法题)