单手杀穿经典链表题Pt.1——LeetCode天梯渡劫(移除节点,反转链表,中间节点)

简介: 移除链表元素🤔

image.png

思路:

我的评价是有手就行,就相当于链表的删除操作,进行遍历,遍历过程中找到目标值进行覆盖就行,注意一下这里我们采用哨兵位节点,也称为哑节点,开辟出来指向链表头节点,可以使对头节点的操作变简单很多,这个哨兵位节点的值可以不考虑,他只是用来攀搭头结点的舔狗(呜呜)。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 struct ListNode* removeElements(struct ListNode* head, int val){
    struct ListNode* dummyHead = malloc(sizeof(struct ListNode));
    dummyHead->next = head;
    struct ListNode* curr = dummyHead;//定义哨兵位节点
    while (curr->next) {
        if (curr->next->val == val) {
            curr->next = curr->next->next;//遍历到目标点进行覆盖
        } 
        else 
        {
            curr = curr->next;
        }
    }
    head = dummyHead->next;
    free(dummyHead); //有借有还,记得归还哨兵位节点和申请的空间  
    return head;
}

反转链表🤔

链接:反转链表

题目:给你单链表的头节点 head ,请你反转链表,并返回反转后的链表

示例 :

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

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

image.png

思路:

1.创建一个新的中间节点我命名为 next ,将当前节点的下一个节点存放在next 节点中

2.链接 next 和当前节点,将 next 指向 当前节点实现反转,将原来指向下一节点的内容销毁掉(头部指向NIULL即可);

3.重复上述过程即可


以上是整体思路实现,而代码实现我们有两条路可以走,分别是迭代和递归,实现思路是一样的:


迭代:

struct ListNode* reverseList(struct ListNode* head){
struct ListNode* next = NULL;
struct ListNode* prev = NULL;
while(head)
{   
next = head->next;
head->next = prev;
prev = head;
head = next;
}
return prev;
}

递归:

递归又分为了向前递归和向后递归,一般采用从前向后递归:

struct ListNode* reverse(struct ListNode* cur,struct ListNode* prev)
{
if(cur==NULL)
{
    return prev;
}
 struct ListNode* next = cur->next;
cur->next = prev;
return reverse(next,cur); //可以与双指针法对比,其实逻辑是一样的,只是用递归实现而已
}
struct ListNode* reverseList(struct ListNode* head)
{
return reverse(head,NULL);
}

从后向前递归:

struct ListNode* reverseList(struct ListNode* head)
{
if(!head || !head->next)
return head;
struct ListNode* cur =  reverseList(head->next);//反转第二个节点后的所有节点
head->next->next = haed;//反转第二个节点与头节点
head->next = NULL;//头节点处理
return cur;
}

链表的中间结点🤔

链接:链表的中间结点

给定一个头结点为 head 的非空单链表,返回链表的中间结点,如果有两个中间结点,则返回第二个中间结点。

奇数个返回中间节点:

image.png


思路:

方法一就是老老实实去遍历链表,算出链表长度,再找出中间节点位置,走过去返回他,属于暴力求解,笨且效率不高,这里就不做代码展示;

方法二巧用快慢指针,如下图:

image.png

我们定义两个指针,慢指针一次走一步,快指针一次走两步,不管链表节点数是奇是偶,慢指针最后必定落在中间节点;当链表节点为偶数个时,最后快指针将落在最后一个节点上,所以只需要判断快指针的 next 节点为不为空即可

struct ListNode* middleNode(struct ListNode* head){
    struct ListNode* guard = malloc(sizeof(struct ListNode));
    guard->next = head;//定义哨兵位节点
struct ListNode* fast = guard;
struct ListNode* slow = guard;
while(fast)
{
    slow = slow->next;//慢指针一次走一步
    if(fast->next)
    {
    fast = fast->next->next;//快指针一次走两步
    }
    else
    {
        return slow;
    }
}
return slow;
}


相关文章
|
4天前
|
算法
LeetCode第24题两两交换链表中的节点
这篇文章介绍了LeetCode第24题"两两交换链表中的节点"的解题方法,通过使用虚拟节点和前驱节点技巧,实现了链表中相邻节点的交换。
LeetCode第24题两两交换链表中的节点
|
4天前
|
存储 算法
LeetCode第86题分隔链表
文章介绍了LeetCode第86题"分隔链表"的解法,通过创建两个新链表分别存储小于和大于等于给定值x的节点,然后合并这两个链表来解决问题,提供了一种简单易懂且操作原链表的解决方案。
LeetCode第86题分隔链表
|
4天前
|
存储 算法
LeetCode第83题删除排序链表中的重复元素
文章介绍了LeetCode第83题"删除排序链表中的重复元素"的解法,使用双指针技术在原链表上原地删除重复元素,提供了一种时间和空间效率都较高的解决方案。
LeetCode第83题删除排序链表中的重复元素
|
4天前
|
算法
LeetCode第23题合并 K 个升序链表
这篇文章介绍了LeetCode第23题"合并K个升序链表"的解题方法,使用分而治之的思想,通过递归合并链表的方式解决了这个难题。
LeetCode第23题合并 K 个升序链表
|
4天前
|
算法
LeetCode第92题反转链表 II
文章分享了LeetCode第92题"反转链表 II"的解法,通过使用四个指针来记录和更新反转链表段的头部、尾部以及前一个和后一个节点,提供了一种清晰且易于理解的解决方案。
LeetCode第92题反转链表 II
|
4天前
|
算法
LeetCode第21题合并两个有序链表
该文章介绍了 LeetCode 第 21 题合并两个有序链表的解法,通过创建新链表,依次比较两个链表的头节点值,将较小的值插入新链表,直至其中一个链表遍历完,再将另一个链表剩余部分接到新链表后面,实现合并。
LeetCode第21题合并两个有序链表
|
4天前
|
算法
LeetCode第19题删除链表的倒数第 N 个结点
该文章介绍了 LeetCode 第 19 题删除链表的倒数第 N 个结点的解法,通过使用快慢双指针,先将快指针移动 n 步,然后快慢指针一起遍历,直到快指针到达链尾,从而找到倒数第 N 个结点的前一个结点进行删除,同时总结了快慢指针可减少链表遍历次数的特点。
LeetCode第19题删除链表的倒数第 N 个结点
|
14天前
|
Python
【Leetcode刷题Python】剑指 Offer 22. 链表中倒数第k个节点
Leetcode题目"剑指 Offer 22. 链表中倒数第k个节点"的Python解决方案,使用双指针法找到并返回链表中倒数第k个节点。
32 5
|
14天前
|
Python
【Leetcode刷题Python】剑指 Offer 18. 删除链表的节点
Leetcode题目"剑指 Offer 18. 删除链表的节点"的Python解决方案,通过使用双指针法找到并删除链表中值为特定数值的节点,然后返回更新后的链表头节点。
25 4
|
11天前
|
算法 Java
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
LeetCode初级算法题:环形链表+排列硬币+合并两个有序数组java解法
18 0