链表的经典算法OJ题

发布时间:2024年01月24日

前言

hello,大家好呀,我是Humble,本篇博客要分享的内容是关于链表的一些力扣OJ题

OK,废话不多说,我们直接开始吧~

?

c24466f5783e41fa8a2266de1937d75c.png

题目一

?

203. 移除链表元素 - 力扣(LeetCode)

?

题目描述:

给你一个链表的头节点?head?和一个整数?val?,请你删除链表中所有满足?Node

val == val?的节点,并返回?新的头节点

bc9d2739492f4fff98cd11c6ed46c0ce.png

?

4e4335c9bc074c89a0f862cde31a6459.png

?

思路一:遍历原链表,遇到val就执行删除 val 节点的操作

这是一种很容易想到的思路,BUT,执行删除操作修改指针的指向有点麻烦,有没有其他办法?

?

接下来我们看一下思路二:

定义新链表,遍历原链表找不为val的节点,尾插在新链表上

?

代码如下:

struct ListNode* removeElements(struct ListNode* head, int val)
 {
    struct ListNode* newHead = NULL;
    struct ListNode* newTail = NULL;

    struct ListNode* pcur = head;//pur用来遍历链表

    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;

}

运行结果:
?

21a1974b0d9f4ccdbb098d28337b5312.png

?

?

题目二

?

206. 反转链表 - 力扣(LeetCode)

?

题目描述

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

ce708dcb4aa0453a8ff040d5cb4e5577.png

?

299b854ffc49480b83d50c12a39e94c9.png

?

这里有一个点值得注意,链表的指针是只能指向后面的,不能反过来,这也是它的一个特性

?

思路:创建三个指针n1,n2,n3分别记录前驱节点,当前节点,后继节点,改变原链表指针指向

代码如下:

struct ListNode* reverseList(struct ListNode* head) 
{
    if (head == NULL) //如果是空链表,直接返回
        return head;
    
   struct ListNode* n1, *n2, *n3;
   n1 = NULL;
   n2 = head;
   n3 = head->next;
   
   while (n2)
   {
      n2->next = n1;
      n1 = n2;
      n2 = n3;
      if (n3) n3 = n3->next;

   }

  return n1;
}

运行结果如下:
cf60e622c8a94fa1a12eded40b827616.png

?

?

题目三

?

21. 合并两个有序链表 - 力扣(LeetCode)

?

题目描述:将两个升序链表合并为一个新的?升序?链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

69a53fc4215d4c1a9a848c7e2883ffc6.png

958ef03b327540f381c9136f1b30303d.png

?

对于这道题,我们很直接的会想到要创建一个新链表

而且,如果有看过我的上一篇关于顺序表的算法OJ题博客的小伙伴可能会发现,

本题与那里的题目二——合并两个有序数组有点相像

?

下面是这道题的代码:

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) 
{
   
     if (list1 == NULL)  return list2;
     if (list2 == NULL)  return list1;
     
     struct ListNode* l1 = list1;
     struct ListNode* l2 = list2;

     struct ListNode* newHead,*newTail; 
     newHead = newTail = (struct ListNode*)malloc(sizeof(struct ListNode));
  
     while (l1 && l2)
     {
         if (l1->val < l2->val)
           { 
              newTail->next = l1;
              newTail = newTail->next;
              l1 = l1->next;
            }
        
         else
          {
            newTail->next = l2;
            newTail = newTail->next;
            l2 = l2->next;
          }
     }

     if (l1)  newTail->next = l1;
     if (l2)  newTail->next = l2;
    
     struct ListNode* ret = newHead->next;
     free(newHead);
     return ret;
}


运行结果:

f71b3874e3824b488dca97224b58ccb5.png

?

?

?

?

题目四

?

876. 链表的中间结点 - 力扣(LeetCode)

?

题目描述:

给你单链表的头结点?head?,请你找出并返回链表的中间结点

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

e5e8aca035ea46228bc5e79201cf515b.png

?

a9668b4dfea24baf908052b1ec6fb7f4.png

?

2483f2c3bd4b438c8228dd9a9cedf182.png

?

对于这道题,Humble的思路是快慢指针

定义两个变量slow和fast

slow每走一步,fast走两步

?

代码如下:

struct ListNode* middleNode(struct ListNode* head)
 {
    struct ListNode* slow,*fast;
    slow = fast =head;

    while(fast && fast->next) //两个条件顺序不能换!
    {
          slow = slow->next;//slow走一步
          fast = fast->next->next;//fast走两步

    }

   return slow;
}

?

运行结果如下:
cb681562c18c4189afcd20c7e99b6e88.png

?

?

题目五

?

面试题 02.04. 分割链表 - 力扣(LeetCode)

?

题目描述:

给你一个链表的头节点?head?和一个特定值?x?,请你对链表进行分隔,使得所有?小于?x?的节点都出现在?大于或等于?x?的节点之前

f2bf1f89e1b74e0f9880411e7c3f3b7d.png

?

5495caf156474eecab901b31f4123df6.png

?

对于这道题,Humble的思路是:定义两个链表,分别放?小于?x?的 与?大于或等于?x?的

通过遍历原链表分别放进对应的新链表中,最后两个链表按顺序首尾相连

?

代码如下:

struct ListNode* partition(struct ListNode* head, int x)
{
if (head ==NULL) //空链表直接返回
     return head;

struct ListNode*greaterHead,*greaterTail;
struct ListNode*lessHead,*lessTail;

greaterHead = greaterTail = (struct ListNode*)malloc(sizeof(struct ListNode));
lessHead = lessTail = (struct ListNode*)malloc(sizeof(struct ListNode));

struct ListNode* pcur = head;
while (pcur)
    {  
         if (pcur ->val <x)
         {
             lessTail->next = pcur;
             lessTail = lessTail->next;
         }
        else 
        {
         greaterTail->next = pcur;
         greaterTail = greaterTail->next;
        }
      pcur =  pcur->next;
    }
    
greaterTail->next = NULL;//将大链表尾部置为NULL,防止链表循环

lessTail->next = greaterHead->next;

    
    return lessHead->next;
}

运行结果如下:

040fc8b65147474b9c019a650c5761b2.png

?

?

?

结语

好了,今天关于链表的五道OJ题的分享就到这里了,如果对大家有帮助就太好啦~

在学习编程的道路上Humble与各位同行,加油吧各位!

最后希望大家点个免费的赞或者关注吧(感谢感谢),也欢迎大家订阅我的专栏

让我们在接下来的时间里一起成长,一起进步吧!

e0d3d2143b284925a6e6d82b6cd73662.png

?

?

文章来源:https://blog.csdn.net/2301_79345909/article/details/135773158
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。