链表刷题笔记(较难篇) (c实现)(跑路人笔记)

简介: 链表刷题笔记(较难篇) (c实现)(跑路人笔记)

前言

本篇包含牛客两道较难题和部分简单题,前面的简单题有为后面的难题做铺垫

前两道题是为第三道较难题做铺垫

对了前面两道题我之前有篇博客写了所以我直接沾过来了=-=.

然后好像被检测啥的了我弄成自己可见了=-=大家见谅.🙃

要是感觉有不懂的可以私聊或评论我,我马上改👍


翻转单链表–力扣简单👍

正确代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* reverseList(struct ListNode* head)
{
    struct ListNode* cur = head;
    struct ListNode* prev = NULL;
    while(cur!=NULL)
    {
       struct ListNode* next = cur->next;
       cur->next = prev;
       prev = cur;
       cur = next; 
    }
    return prev;
}



思路

我的思路是将链表的指针进行翻转

比如:


image.png

要翻转这个链表

我们就要知道链表的上一位,下一位

然后让当前的链表内容的next指向上一位,然后通过next变量向下移动链表当当前内容为NULL时停止循环.

所以这道题只需要三个变量就可以解决问题=-=.


链表的中间节点–力扣简单👍

连接

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

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


正确代码

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
struct ListNode* middleNode(struct ListNode* head)
{
    assert(head);
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while(fast!=NULL&&fast->next!=NULL)
    {
        slow = slow->next;
        fast = fast->next->next;
    }
    return slow;
}



讲解

使用快慢指针,慢指针向后走一步的时候快指针走两步就好了=-=.

思路很简单但是其实还挺难想的=-=.


链表的回文结构(牛客较难)🤦‍♂️

连接

image.png

回文结构:


指逆置后和正序一致的数据如1221逆置后还是1221所以1221为true

再如123 逆置后为321 就不为回文结构.


不得不说一句,牛客的题目描述和报错实在是做的一般般🤦‍♂️.

今天不小心调用了空指针他直接给我个段报错实在是难受🤦‍♂️.


不小心发了点牢骚=-=.我们继续


正确代码

提醒一下虽然这是C++形势的代码但是内部都是C写的所以大家不用被劝退💕


/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) 
    {
        ListNode*fast=A ,*slow=A,*cur=NULL,*next=NULL,*prev=NULL;
        while(fast&&fast->next)
        {
            fast = fast->next->next;
            slow = slow->next;
        }
        next = slow->next;
        prev = NULL;
        cur = slow;
        while(cur)
        {
            cur->next = prev;
            prev = cur;
            cur = next;
            next = next->next;
        }
        ListNode* newhead1 = A;
        ListNode* newhead2 = prev;
        while(newhead2)
        {
            if(newhead1->val ==newhead2->val)
            {
                newhead1 = newhead1->next;
                newhead2 = newhead2->next;
            }
            else
            {
                return false;
            }
        }
        return true;
    }
};



讲解

我们这道题的思路是先通过快慢指针找到链表的中间节点,然后通过三个指针进行中间节点后的逆置,最后再通过遍历进行比较

整体思路的时间复杂度为O(N)空间复杂度为O(1)符合题目要求👍


 

while(fast&&fast->next)
        {
            fast = fast->next->next;
            slow

= slow->next;

       }


寻找中间节点通过快慢指针.


next = slow->next;
        prev = NULL;
        cur = slow;
        while(cur)
        {
            cur->next = prev;
            prev = cur;
            cur = next;
            next = next->next;
        }



逆序后面部分的链表内容


 

ListNode* newhead1 = A;
        ListNode* newhead2 = prev;
        while(newhead2)
        {
            if(newhead1->val == newhead2->val)
            {
                newhead1 = newhead1->next;
                newhead2 = newhead2->next;
            }
            else
            {
                return false;
            }
        }
        return true;
    }



在赋值时我将A给newhead1我相信大家都能理解

把prev赋值给newhead2是将逆序后的头给newhead2👍


比较逆序后的部分,以newhead2为循环的终止条件


分为三种情况


正常情况如1221

中间为对称点情况12321

非回文情况1212

正常情况如1221下的newhead2应该在1221的第三个元素的位置及2的位置

这部分已经为逆置过的情况所以情况现在应该从1221变为两个1->2->2->NULL(注:这部分没错,在逆序时我们的第一个链表确实是这种情况,因为我们是将第三个元素的next置为空的👍)

第二个链表情况应该为1->2->NULL而我们的第一个链表.所以我们只需要比较从第二个链表的头到NULL即可👍.


中间为对称点的情况


及12321时也是因为逆序分成了两个链表


1->2->3->NULL

1->2->3->NULL

这时无论以谁为结束条件都可👍

非回文的情况

直接在后续循环里的else判断去除了👍.

这样一道难题就解决了🤪.


结尾

舒文想要机器人,呜呜呜呜呜😭😭.


相关文章
|
1月前
|
Python
【Leetcode刷题Python】21. 合并两个有序链表
介绍了几种不同的方法来合并多个已排序的链表,包括暴力求解、使用小顶堆以及分而治之策略。
33 2
|
1月前
|
程序员
【刷题记录】移除链表元素
【刷题记录】移除链表元素
|
1月前
|
索引 Python
【Leetcode刷题Python】328. 奇偶链表
在不使用额外空间的情况下,将链表中的奇数和偶数索引节点重新排序的方法,并提供了相应的Python实现代码。
28 0
|
1月前
|
Python
【Leetcode刷题Python】25.K 个一组翻转链表
解决LeetCode "K 个一组翻转链表" 问题的三种方法:使用栈、尾插法和虚拟节点顺序法,并提供了每种方法的Python实现代码。
26 0
|
1月前
|
Python
【Leetcode刷题Python】114. 二叉树展开为链表
LeetCode上114号问题"二叉树展开为链表"的Python实现,通过先序遍历二叉树并调整节点的左右指针,将二叉树转换为先序遍历顺序的单链表。
21 3
【Leetcode刷题Python】114. 二叉树展开为链表
|
1月前
【刷题记录】链表的回文结构
【刷题记录】链表的回文结构
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 22. 链表中倒数第k个节点
Leetcode题目"剑指 Offer 22. 链表中倒数第k个节点"的Python解决方案,使用双指针法找到并返回链表中倒数第k个节点。
40 5
|
1月前
|
Python
【Leetcode刷题Python】剑指 Offer 18. 删除链表的节点
Leetcode题目"剑指 Offer 18. 删除链表的节点"的Python解决方案,通过使用双指针法找到并删除链表中值为特定数值的节点,然后返回更新后的链表头节点。
31 4
|
1月前
|
存储 Python
【Leetcode刷题Python】23. 合并K个升序链表
合并K个升序链表的方法:使用数组排序的暴力求解法、使用小顶堆的高效方法,以及分而治之的策略,并提供了相应的Python实现代码。
13 1
|
1月前
|
Python
【Leetcode刷题Python】138. 复制带随机指针的链表
LeetCode上题目“138. 复制带随机指针的链表”的Python解决方案,包括两种方法:一种是在每个节点后复制一个新节点然后再分离出来形成新链表;另一种是构建一个字典来跟踪原始节点与其副本之间的映射关系,从而处理新链表的构建。
14 1