【数据结构】(图解)leetcode刷题之单链表(中)

👋大家好呀!这个是付青云同学的博客
目前一直在学习C语言。🐸
写博客是为了来记录我的学习过程,同时也希望通过博客能够帮助到需要帮助的人。
如果我的博客可以帮助到你,不妨给我一个关注哦😁!

在这里插入图片描述
最近在学数据结构,学了的知识后当然要巩固一下,所以就找了一些经典的链表题写一写,同时也分享一下我做题的一些思路。
另外:这个系列文章将会有上中下三部分,难度递增,下篇努力正制作中。。。
【数据结构】(图解)力扣刷题之单链表(上)

合并两个有序链表

题目描述如下(具体可以点击上方链接):
在这里插入图片描述
思路:

  1. 首先比较两个链表的头节点,将小的头节点放入直接创建的变量中
  2. 之后继续比较两个链表val大小,尾插

如图:
请添加图片描述
注意:当有一个链表为空时,就直接返回另外一个链表
代码如下:

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2)
{
    if(list1==NULL)
        return list2;
    if(list2==NULL)
        return list1;
    struct ListNode* head=NULL,*tail=NULL;
    //将小的头节点放在head中
    if(list1->val<list2->val)
    {
        head=tail=list1;
        list1=list1->next;
    }
    else
    {
        head=tail=list2;
        list2=list2->next;
    }
    //比较节点大小,尾插
    while(list1&&list2)
    {
        if(list1->val<list2->val)
        {
            tail->next=list1;
            tail=tail->next;
            list1=list1->next;
        }
        else
        {
            tail->next=list2;
            tail=tail->next;
            list2=list2->next;
        }
    }
    //将两个链表的尾节点放入
    if(list1)
    {
        tail->next=list1;
    }
    if(list2)
    {
        tail->next=list2;
    }
    return head;
}

链表分割

题目描述如下(具体可以点击上方链接):
在这里插入图片描述
思路:
开辟两个新链表(lessHead和graterHead),将小于x的节点放入lessHead中,将大于等于x的节点放入graterHead中;最后将两个链表连接起来即可。

注意:在开辟空间的时候,最后一定要记得释放!

如图:
请添加图片描述
代码如下:

struct ListNode* partition(struct ListNode* pHead, int x)
{
     struct ListNode* lessHead,*greaterHead,*lessTail,*greaterTail;
        //创建哨兵位
        lessHead=lessTail=(struct ListNode*)malloc(sizeof(struct ListNode));
        lessTail->next=NULL;
        greaterHead=greaterTail=(struct ListNode*)malloc(sizeof(struct ListNode));
        greaterTail->next=NULL;
        
        struct ListNode* cur=pHead;
        while(cur)
        { 
            if(cur->val < x)
            { 
                lessTail->next=cur;
                lessTail=cur;
            }
            else
            {
                greaterTail->next=cur;
                greaterTail=cur;
            }
            cur=cur->next;
        }
        lessTail->next=greaterHead->next;
        greaterTail->next=NULL;
        
        struct ListNode* newnode=lessHead->next;
        //注意要释放
        free(lessHead);
        free(greaterHead);
        return newnode;
}

链表的回文结构

题目描述如下(具体可以点击上方链接):
在这里插入图片描述
思路:
首先找到链表的中间结点,将中间结点之后的链表翻转,之后再跟节点之前的链表比较,如果全部相同,输出true,反之输出false
链表的中间结点和反转链表
代码如下:

bool isPalindrome(struct ListNode* head)
{
    //找出中间节点
    struct ListNode* slow,*fast;
    slow=fast=head;
    while(fast && fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    //中间节点逆置
    struct ListNode* n1,*n2,*n3;
    n1=NULL;
    n2=slow;
    n3=slow->next;
    while(n2)
    {
        n2->next=n1;
        n1=n2;
        n2=n3;
        if(n3)
        {
            n3=n3->next;
        }
    }
    //比较
    while(n1 && head)
    {
        if(head->val != n1->val)
        {
            return false;
        }
        else
        {
            n1=n1->next;
            head=head->next;
        }
    }
    
    return true; 
}

相交链表

题目描述如下(具体可以点击上方链接):
在这里插入图片描述

方法一:暴力求解法

思路:
就是将每个节点比较,如果有相同的节点则说明相交
代码如下:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    struct ListNode* n1=headA;
   
    while(n1)
    {
        struct ListNode* n2=headB;
        while(n2)
        {
            if(n1==n2)
            {
                return n1;
            }
            else if(n1->next==n2->next)
            {
                return n1->next;
            }
            else
            {
                n2=n2->next;
            }
        }
        n1=n1->next;
    }
    return NULL;
}

方法二:比尾相差法

思路:

  1. 将两个链表的长度求出,得到它们它们的长度之差k,
  2. 让长链表先走k步,随后两个链表一起走并且比较next

如果有相同的next,就说明是相交的链表

代码如下:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    struct ListNode* n1=headA;
    struct ListNode* n2=headB;
    int t1=1;
    int t2=1;
    int n;
    while(n1->next)
    {
        n1=n1->next;
        t1++;
        
    }
    while(n2->next)
    {
        n2=n2->next;
        t2++;
    }
    //判断相交
    struct ListNode* nA=headA;
    struct ListNode* nB=headB;
    if(n1==n2)
    {
      //找出相交点
        //1.求出两链表长度
        //2.齐头并进
        n=abs(t1-t2);
        while(n--)
        {
            if(t1>t2)
            {
                nA=nA->next;
            }
            else
            {
                nB=nB->next;
            }
        }
        while(nA!=nB)
        {
            nA=nA->next;
            nB=nB->next;
        }
    }
    else
    {
        return NULL; 
    }
    
    return nA;
}
  • 30
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 27
    评论
评论 27
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

付青云同学

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值