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

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

🌺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;
    }
};

相关文章
|
1月前
|
存储
链表题目练习及讲解(下)
链表题目练习及讲解(下)
25 9
|
1月前
|
存储 Java
HashMap之链表转红黑树(树化 )-treefyBin方法源码解读(所有涉及到的方法均有详细解读,欢迎指正)
本文详细解析了Java HashMap中链表转红黑树的机制,包括树化条件(链表长度达8且数组长度≥64)及转换流程,确保高效处理大量数据。
71 1
|
1月前
链表题目练习及讲解(上)
链表题目练习及讲解(上)
23 1
|
5月前
|
存储 SQL 算法
LeetCode 题目 86:分隔链表
LeetCode 题目 86:分隔链表
|
5月前
|
SQL 算法 数据可视化
LeetCode题目92:反转链表ll 【python 递归与迭代方法全解析】
LeetCode题目92:反转链表ll 【python 递归与迭代方法全解析】
|
5月前
|
算法
【经典LeetCode算法题目专栏分类】【第7期】快慢指针与链表
【经典LeetCode算法题目专栏分类】【第7期】快慢指针与链表
|
5月前
|
存储 SQL 算法
LeetCode 题目 82:删除排序链表中的重复元素 II
LeetCode 题目 82:删除排序链表中的重复元素 II
|
6月前
【移除链表元素】LeetCode第203题讲解
【移除链表元素】LeetCode第203题讲解
|
5月前
|
存储 SQL 算法
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
LeetCode力扣第114题:多种算法实现 将二叉树展开为链表
|
5月前
|
存储 算法 Java
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
【经典算法】Leetcode 141. 环形链表(Java/C/Python3实现含注释说明,Easy)
52 2