【Leetcode&nowcode&数据结构】单链表的应用(初阶)

系列文章目录

《Leetcode&nowcode代码强化刷题》


文章目录


前言

数据结构与算法是计算机领域的核心,既是面试考察重点,也是优化项目性能的关键。而刷题是掌握它最有效的方式,能帮我们巩固理论、提升解题能力。​

我选择LeetCodeNowCode 作为主要刷题平台:LeetCode 题目丰富、分类清晰,适合夯实基础;NowCode 贴近国内企业笔试场景,助力对接实战需求,二者互补性强。​

这份刷题记录不只是题目与答案的罗列,更会记录解题思路、难点易错点,以及解法优化过程。希望它能成为我的复盘工具,也为其他学习者提供参考。​

接下来,就从第一道题开始,在刷题中积累提升,让数据结构与算法成为解决问题的有力工具。


正文

一.移除链表元素

题目链接203.移除链表元素
题目描述

解题思路 :创建新链表,把原链表中的值依次尾插到新链表的尾部

代码展示

c 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

typedef struct ListNode LTN;
struct ListNode* removeElements(struct ListNode* head, int val) {

    LTN* newHead = NULL; // 新头
    LTN* pcur = head;    // 遍历链表
    LTN* newTail = NULL; // 新尾
    while (pcur) {
        if (pcur->val != val) // 符合要求
        {
            // 尾插
            if (newHead == NULL) // 新链表为空

                newHead = newTail = pcur;

            // 新链表不为空
            else {
                newTail->next = pcur;
                newTail = newTail->next;
            }
        }
        pcur = pcur->next;
    }

    if (newTail)
        newTail->next = NULL;
    return newHead;
}

博主题解


二.反转链表

题目链接206.反转链表
题目描述

解题思路:

创建三个指针,分别指向,前一个节点,当前节点,后一个节点

依次反转当前节点的指向,利用后一个节点来 让三个指针继续向后走

代码展示

c 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode LTN;
struct ListNode* reverseList(struct ListNode* head) {
    if(head==NULL)
    {
        return head;
    }
    //定义三个指针
LTN* n1=NULL,*n2=head,*n3=n2->next;
//开始遍历
while(n2)//n2不为空
{
n2->next=n1;
n1=n2;
n2=n3;
if(n3)//如果3不为空的时候
n3=n3->next;

}
    return n1;
}

博主题解


三.链表的中间结点

题目链接876.链表的中间结点
题目描述

解题思路

创建一个快指针,一个慢指针

快指针每次走两步

慢指针每次走一步

当快指针走完,慢指针指向的就是链表的中间结点

代码展示

c 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode LTN;
struct ListNode* middleNode(struct ListNode* head) {
    //创建快慢指针
    LTN* fast=head;
    LTN* slow=head;
    //慢指针走一步,快指针走两步
    while(fast!=NULL&&fast->next!=NULL)//不能换顺序,要先确保fast不为NULL
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    
    return slow;
}

博主题解


四.合并两个有序链表

题目链接21.合并两个有序链表
题目描述

解题思路

创建一个哨兵位,依次比较两个链表的值,按序插入新链表

一个链表插完,把另一个剩下的直接插到后面

代码展示

c 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode LTN;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    LTN* newhead=malloc(sizeof(LTN));//创建链表哨兵位
    newhead->next=NULL;
    LTN* l1=list1;
    LTN* l2=list2;
LTN* newTail=newhead;
while(l1!=NULL&&l2!=NULL)
{
    if(l1->val>l2->val)
    {
newTail->next=l2;
newTail=newTail->next;
l2=l2->next;
    }
    else
    {
        newTail->next=l1;
        newTail=newTail->next;
        l1=l1->next;
    }
}

if(l1!=NULL)
{
    newTail->next=l1;
}
if(l2!=NULL)
{
    newTail->next=l2;
}
return newhead->next;
}

博主题解


五.链表的回文结构

题目链接链表的回文结构
题目描述

解题思路

会了上面两道,这道题目就很简单了

先快慢指针找中间节点

从中间节点开始三指针逆置

逆置完比较

逆置完之后,对逆置那部分链表与原来的链表进行比较

代码展示

c 复制代码
/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
//快慢指针找中间节点
ListNode* FindMid(ListNode* head)
{
ListNode* fast=head;
ListNode* slow=head;
while(fast->next!=NULL&&fast!=NULL)
{
    slow=slow->next;
    fast=fast->next->next;
}
return slow;
}

ListNode* reList(ListNode* head)//三指针反转链表
{
   if(head==NULL)
   return head;
   ListNode* n1=NULL,*n2=head,*n3=head->next;
   while(n2!=NULL)
   {
    n2->next=n1;
    n1=n2;
    n2=n3;
    if(n3!=NULL)
    n3=n3->next;
   }
   return n1;
}

class PalindromeList {
public:
    bool chkPalindrome(ListNode* A) {
       ListNode* mid=FindMid(A);//找中间节点
       ListNode* newhead=reList(mid);//反转后新节点
       while(newhead!=NULL)
       {
        if(newhead->val!=A->val)
        return false;
        else
        {
            newhead=newhead->next;
            A=A->next;
        }
       }
       return true;
    }
};

博主题解


六.相交链表

题目链接160.相交链表
题目描述

解题思路

单链表,方向唯一

如果相交,那么最后肯定会到相同的终点

由于交点之后的路程一样,差别就在前面

①分别计算两个链表的长度

②计算差值

③让长链表先走差的绝对值步,这样两个链表到交点距离相同了

④再一起走到的同一个位置,就是交点了

代码展示

c 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode LTN;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    //相交链表,必有相同的终点
    //计算两条链表的长度
    int lenA=0,lenB=0;
    LTN* pa=headA;
    LTN* pb=headB;
    while(pa!=NULL)
    {
        pa=pa->next;
        lenA++;
    }
    while(pb!=NULL)
    {
        pb=pb->next;
        lenB++;
    }
    //计算长度差的绝对值
    size_t cnt=abs(lenA-lenB);
    //定义长短指针
LTN* longList=headA;
LTN* shortList=headB;    
//根据实际情况调整
if(lenA<lenB)
{
longList=headB;
shortList=headA;
}
//让长指针先走
while(cnt--)
{
longList=longList->next;
}
//长短指针一起走
while(longList!=NULL)
{
    if(longList==shortList)
    {
        return longList;
    }
    longList=longList->next;
    shortList=shortList->next;
}
//出来了说明不是相交链表
return NULL;


}

博主题解


七.环形链表I

题目链接:141.环形链表

题目描述:

解题思路:

快慢指针,如果最后两个指针相遇,就存在环

兔子和乌龟在跑道上面跑,兔子套了乌龟一圈,最后二者会相遇,说明跑道是圆形的,即存在环

代码展示:

c 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
typedef struct ListNode LTN;
bool hasCycle(struct ListNode* head) {
    // 快慢指针
    LTN* fast = head;
    LTN* slow = head;
    while (fast != NULL && fast->next !=NULL) // 顺序不能变,防止空指针解引用
    {
          slow = slow ->next;
            if(fast->next!=NULL)
        fast = fast->next->next;
        //相遇
        if (fast == slow)
            return true;
    }
    return false;
}

博主题解


八.环形链表II

题目链接:142.环形链表II

题目描述:

解题思路:

这里需要掌握一个技巧,就是找到相遇结点之后,我们再分别从头结点和相遇结点开始向后依次遍历,两个指针会在入环结点相遇,证明如下:

(字有点丑,大家不要介意ovo)

代码展示:

c 复制代码
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode LTN;
struct ListNode *detectCycle(struct ListNode *head) {
    
    // 快慢指针
    LTN* fast = head;
    LTN* slow = head;
    while (fast != NULL && fast->next !=NULL) // 顺序不能变,防止空指针解引用
    {
          slow = slow ->next;
            if(fast->next!=NULL)
        fast = fast->next->next;
        //找到后和头一起向后遍历,就会相遇
        if (fast == slow)
            {
LTN* pcur=head;
while(fast!=NULL)
{
     if(fast==pcur)
    return pcur;
    fast=fast->next;
    pcur=pcur->next;
}
            }
    }
    return NULL;
}

博主题解


总结

单链表部分的题目,我们需要去多多注意一些空链表的情况(博主刚开始写WA了好多次),掌握一些快慢指针的用法,和一些技巧,下一篇我会为大家带来单链表进阶题目,希望大家可以多多支持,有什么问题可以评论留言或者后台私信,感谢大家

后续会开始感谢数据结构相关的知识性内容,C语言栏会再上上传一些剩下的知识性内容!!!

相关推荐
草莓工作室4 小时前
AT指令解析:TencentOS Tiny AT指令解析源码分析2-数据类型定义
c语言·at指令·tencentos tiny
JAVA学习通4 小时前
JDK高版本特性总结与ZGC实践
java·jvm·算法
syty20204 小时前
简简单单区块链
算法·哈希算法
CoovallyAIHub4 小时前
CLIP, DINO等多模型融合DreamSim,让电脑“看懂”图片有多像!模型融合成为热门!
深度学习·算法·计算机视觉
骁的小小站4 小时前
Learn C the Hardway学习笔记和拓展知识(一)
c语言·开发语言·c++·经验分享·笔记·学习·bash
Giser探索家4 小时前
遥感卫星升轨 / 降轨技术解析:对图像光照、对比度的影响及工程化应用
大数据·人工智能·算法·安全·计算机视觉·分类
仰泳的熊猫5 小时前
LeetCode:700. 二叉搜索树中的搜索
数据结构·c++·算法·leetcode
嵌入式-老费5 小时前
Easyx图形库应用(图形旋转)
算法
代码充电宝5 小时前
LeetCode 算法题【中等】189. 轮转数组
java·算法·leetcode·职场和发展·数组