LeetCode 链表OJ分享

删除排序链表中的重复元素

链接: link
题目描述:
在这里插入图片描述
题目思路:

本题思路使用双指针,以示例二为例如下图:
在这里插入图片描述

如果head->val等于next->val,那么此时就要删除重复节点next,具体步骤:
1、创建一个节点指针del记录被删除的节点next
2、next指针向下移动
3、free(del)
4、链接cur和next,cur->next=next

在这里插入图片描述

如果head->val不等于next->val,那么此时就要向下移动节点指针,具体步骤:
cur=next;
next=next->next

在这里插入图片描述

循环结束条件:当next指针指向空时,循环结束,返回链表的头

在这里插入图片描述

本题注意两点:
1、注意链表只有一个节点时,不做删除重复元素的操作,直接返回链表的头。
2、注意如果该链表为空链表,直接返回NULL。

代码实现:

struct ListNode* deleteDuplicates(struct ListNode* head)
{
    if(head==NULL)
    {
        return NULL;
    }
    if((head->next)==NULL)
    {
        return head;
    }
    struct ListNode* cur = head;
    struct ListNode* next = cur->next;
    while(next)
    {
        if(cur->val==next->val)
        {
            struct ListNode* del = next;
            next = next->next;
            cur->next = next;
            free(del);
        }
        else
        {
            cur=cur->next;
            next = next->next;
        }
    }
    return head;
}

回文链表

链接: link
题目描述:
在这里插入图片描述
题目思路:
本题主要核心步骤分为两三大步,第一步就是寻找中间节点,第二步逆置中间节点后的其他节点,第三步分别从头节点和中间节点开始,对比元素是否相等,如果相等为回文链表返回true,不相等返回false。

第一步:寻找中间节点
思路:快慢指针,快指针一次走两步,慢指针一次走一步

偶数节点循环结束条件分析:
循环结束条件为fast=NULL

在这里插入图片描述
在这里插入图片描述
奇数节点循环结束条件分析:
循环结束条件为fast->next=NULL

在这里插入图片描述
在这里插入图片描述
第一步代码实现:

struct ListNode* MiddleNode(struct ListNode* head)
 {
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast = fast->next->next;
    }
    return slow;
 }

第二步:逆置中间节点后的节点
思路:改变链表指向,返回逆置后链表新的头

在这里插入图片描述
在这里插入图片描述

1、三个指针n1 n2 n3,逆置以下图为例

在这里插入图片描述

改变n2的指向,n2->next=n1

在这里插入图片描述

3个指针同时后移:n1=n2 n2=n3 n3=n3->next

在这里插入图片描述

循环上述步骤操作

循环结束条件分析:
本题循环结束条件为n2为空,但是n2为空的同时还要注意n3指针的空指针问题,如下图,n1到达最后一个节点,此时n2刚好为空,但是n3在上述迭代的情况下,下图的位置显然是不正确的。
在这里插入图片描述
此处应该注意加以判断n3是否为空,如果n3为空,则不再进行向下移动的迭代,最后返回n1,即为逆置后链表新的头。
在这里插入图片描述
第二步代码实现:

struct ListNode* reverseNode(struct ListNode* mid)
 {
     struct ListNode* n1 = NULL;
     struct ListNode* n2 = mid;
     struct ListNode* n3 = mid->next;
     while(n2)
     {
         n2->next = n1;
         //迭代
         n1=n2;
         n2=n3;
         if(n3)
         {
             n3=n3->next;
         }
     }
     return n1;
 }

第三步分别从头节点和中间节点开始,对比元素是否相等,如果相等为回文链表返回true,不相等返回false。

经过上述两个步骤的修改后,链表的形态如下图:
在这里插入图片描述
对比元素是否相等,循环结束条件:rmid!=NULL
代码实现:

struct ListNode* MiddleNode(struct ListNode* head)
 {
    struct ListNode* slow = head;
    struct ListNode* fast = head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast = fast->next->next;
    }
    return slow;
 }
 struct ListNode* reverseNode(struct ListNode* mid)
 {
     struct ListNode* n1 = NULL;
     struct ListNode* n2 = mid;
     struct ListNode* n3 = mid->next;
     while(n2)
     {
         n2->next = n1;
         //迭代
         n1=n2;
         n2=n3;
         if(n3)
         {
             n3=n3->next;
         }
     }
     return n1;
 }
bool isPalindrome(struct ListNode* head)
{
    struct ListNode* mid = MiddleNode(head);
    struct ListNode* rmid = reverseNode(mid);
    struct ListNode* cur = head;
    while(rmid)
    {
        if(cur->val==rmid->val)
        {
            cur=cur->next;
            rmid=rmid->next;
        }
        else
        {
            return false;
        }
    }
    return true;
}

剑指Offer 06.从尾到头打印链表

链接: link
题目描述:
在这里插入图片描述
题目思路:

思路同上题: 1、逆置链表,改变链接方向
2、求出链表节点的个数returnSize
3、动态开辟数组,数组元素个数为
returnSize
4、释放动态开辟的内存空间

代码实现:

 int countList(struct ListNode* head)
 {
     int count=0;
     struct ListNode* cur = head;
     while(cur)
     {
         count++;
         cur=cur->next;
     }
     return count;
 }
 struct ListNode* reverseList(struct ListNode* head)
 {
     if(head==NULL)
     {
         return NULL;
     }
     if(head->next==NULL)
     {
         return head;
     }
     struct ListNode* n1 = NULL;
     struct ListNode* n2 = head;
     struct ListNode* n3 = head->next;
     while(n2)
     {
         n2->next = n1;
         n1 = n2;
         n2=n3;
         if(n3)
         {
            n3=n3->next;
         }
     }
     return n1;
 }
int* reversePrint(struct ListNode* head, int* returnSize)
{
    int ret = countList(head);
    *returnSize = ret;
    struct ListNode* newhead = reverseList(head);
    int * tmp = (int*)malloc(sizeof(int)*(*returnSize));
    if(tmp==NULL)
    {
        perror("malloc fail");
        return NULL;
    }
    struct ListNode* cur = newhead;
    int i = 0;
    while(i<ret&&cur)
    {
         tmp[i]=cur->val;
         cur=cur->next;
         i++;
    }
    return tmp;
    free(tmp);
    tmp=NULL;
}

复制带随机指针的链表

链接: link
题目描述:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
题目思路:
1、拷贝节点插入到原节点后面
在这里插入图片描述
步骤:

1、画图明确拷贝节点和原节点

在这里插入图片描述

2、动态开辟一个内存空间存放拷贝节点
struct Node* copy=(struct Node*)malloc(sizeof(struct Node));
将原节点的值赋值给拷贝节点 copy->val=cur->val

3、链接拷贝节点

在这里插入图片描述

4、循环条件:cur!=NULL,循环进行上述步骤

2、控制拷贝节点的random:copy->random=cur->random->next;
在这里插入图片描述
步骤:

1、此时copy节点就在cur节点的后面,cur->next = copy

在这里插入图片描述

2、如果cur原节点的random为空,那么拷贝节点的random也为空

在这里插入图片描述

3、如果原节点的random不为空,拷贝节点的random和原节点的random相等,copy->random=cur->random->next;拷贝节点的random在原节点random的下一个节点。

在这里插入图片描述

4、迭代向下,cur=copy->next

3、拷贝节点从原链表上解下来尾插形成新的链表,并且恢复原链表(具体看图实现)
步骤:

1、将拷贝节点尾插到新的链表

在这里插入图片描述

2、恢复原链表(依次按原链表链接)

在这里插入图片描述

struct Node* copyRandomList(struct Node* head) 
{
    //1、将拷贝节点链接到原节点的后面
    struct Node* cur = head;
    while(cur)
    {
        struct Node* copy = (struct Node*)malloc(sizeof(struct Node));
        copy->val=cur->val;
        //链接
        struct Node* next = cur->next;
        cur->next = copy;
        copy->next = next;
        cur=next;
    }
    //2、控制拷贝节点的random
    cur = head;
    while(cur)
    {
        struct Node* copy = cur->next;
        if(cur->random==NULL)
        {
            copy->random=NULL;
        }
        else
        {
            copy->random=cur->random->next;
        }
        cur=copy->next;
    }
    //3、尾插新链表,恢复原链表
    cur = head;
    struct Node* copyHead = NULL,* copyTail = NULL;
    while(cur)
    {
        struct Node* copy = cur->next;
        struct Node* next = copy->next;
        if(copyHead==NULL)
        {
            copyHead = copyTail=copy;
        }
        else
        {
            copyTail->next = copy;
            copyTail=copyTail->next;
        }
        //恢复原链表
        cur->next = next;
        cur= next;

    }
    return copyHead;
	
}
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Rust 是一种现代的编程语言,特别适合处理内存安全和线程安全的代码。在 LeetCode 中,链表是经常出现的题目练习类型,Rust 语言也是一种非常适合处理链表的语言。接下来,本文将从 Rust 语言的特点、链表的定义和操作,以及 Rust 在 LeetCode链表题目的练习等几个方面进行介绍和讲解。 Rust 语言的特点: Rust 是一种现代化的高性能、系统级、功能强大的编程语言,旨在提高软件的可靠性和安全性。Rust 语言具有如下几个特点: 1. 内存安全性:Rust 语言支持内存安全性和原语级的并发,可以有效地预防内存泄漏,空悬指针以及数据竞争等问题,保证程序的稳定性和可靠性。 2. 高性能:Rust 语言采用了“零成本抽象化”的设计思想,具有 C/C++ 等传统高性能语言的速度和效率。 3. 静态类型检查:Rust 语言支持静态类型检查,可以在编译时检查类型错误,避免一些运行时错误。 链表的定义和操作: 链表是一种数据结构,由一个个节点组成,每个节点保存着数据,并指向下一个节点。链表的定义和操作如下: 1. 定义:链表是由节点组成的数据结构,每个节点包含一个数据元素和一个指向下一个节点的指针。 2. 操作:链表的常用操作包括插入、删除、查找等,其中,插入操作主要包括在链表首尾插入节点和在指定位置插入节点等,删除操作主要包括删除链表首尾节点和删除指定位置节点等,查找操作主要包括根据数据元素查找节点和根据指针查找节点等。 Rust 在 LeetCode链表题目的练习: 在 LeetCode 中,链表是常见的题目类型,而 Rust 语言也是一个非常适合练习链表题目的语言。在 Rust 中,我们可以定义结构体表示链表的节点,使用指针表示节点的指向关系,然后实现各种操作函数来处理链表操作。 例如,针对 LeetCode 中的链表题目,我们可以用 Rust 语言来编写解法,例如,反转链表,合并两个有序链表,删除链表中的重复元素等等,这样可以更好地熟悉 Rust 语言的使用和链表的操作,提高算法和编程能力。 总之,在 Rust 中处理链表是非常方便和高效的,而 LeetCode 中的练习也是一个非常好的机会,让我们更好地掌握 Rust 语言和链表数据结构的知识。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mikk-

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

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

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

打赏作者

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

抵扣说明:

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

余额充值