有关单链表的OJ题(1)

由于单链表本身还存在在缺陷,所以很多OJ题会深挖这些缺陷让问题很多的小明进行解决。本篇文章从力扣和牛客网上选取了以下题目进行题目解答分享:移除链表元素链表的中间结点合并两个有序链表反转链表

如果对单链表有问题的小明,希望数据结构之单链表能够解答你的困惑。

目录

移除链表元素 

链表的中间节点

合并两个有序链表

 反转链表

总结


 

移除链表元素 

思路:在题目分析后,我们知道题目要求我们删除链表中所有的指定元素。

在一开始看到这道题目,第一步我想的是使用一个指针进行对链表元素的遍历,找到指定的元素后直接free。

但是考虑到链表的特性,如果直接删除的话,那么链表原来的连接结构会断连。所以本题需要定义两个指针cur和prev,cur用于对数据的遍历删除,prev则要对cur进行保存操作防止链表的断连。

题解代码:

struct ListNode* removeElements(struct ListNode* head, int val) {
    struct ListNode*cur = head;
    struct ListNode*prev = NULL;
    while(cur)
    {
        if(cur->val==val)
        {
            if(cur==head)
            {
                cur = head->next;
                free(head);
                head = cur;
            }
            else
               {
                   prev->next = cur->next;
                   free(cur);
                   cur = prev->next;
                   
               }
        }
        else{
            prev = cur;
            cur = cur->next;
        }
    }
    return head;
    
}

 在代码中我们注意到了对cur在头结点单独进行处理,若不单独处理在cur = prev->next时,prev已经是一个空指针。

链表的中间节点

 

 思路:由题目可知我们要得到链表的中间结点且分两种情况,一种是一个中间结点,一种是有两个中间节点,此时要返回二者中的后一个结点,这两种情况由结点个数的奇偶决定,要返回中间节点,则改变头结点的位置,需要移动的次数为n/2.

代码如下 

struct ListNode* middleNode(struct ListNode* head) {
    struct ListNode*cur = head;
    struct ListNode*prev = head;
    int count=0;
    while(cur)
    {
        count++;
        cur = cur->next;
    }
    int n = count/2;
    while(n--)
    {
        head= head->next;
    }
    return head;
    
}


合并两个有序链表

思路:我首先想到的是以一个链表为基准,但是发现这样操作起来链表得重新连接很麻烦。于是我决定重新定义头和尾,创建一个新的链表进行填入尾插操作。 很多问题的小明问,指向一个list,list后续的结点不用管了吗?小明啊,该去复习复习链表的结构咯。指向链表的一个结点,由于链表的连接性,后面的结点也是一起连接过来滴。

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    struct ListNode*head = NULL,*tail=NULL;
    if(list1==NULL&&list2 ==NULL)//先对两个链表进行判空操作
    return NULL;
    if(list1==NULL)
    return list2;
    if(list2==NULL)
        return list1;
        while(list1&&list2)
        {
            if(list1->val<list2->val)
            {   if(tail==NULL)//尾结点为空无法尾插
            {
                head =tail =list1;
            }
            else
            {
                tail->next =list1;//尾插,将原来的尾与新尾连接
                tail = tail->next;//插入的值定为新尾
            }
            list1 = list1->next;
            }
            else{
                if(tail==NULL)
                {
                    head =tail =list2;
                }
                else{
                    tail->next =list2;
                    tail =tail->next;
                }
                list2 = list2->next;
            }
        }
        if(list1)
        {
            tail->next =list1;
        }
        if(list2)
        {
            tail->next = list2;
        }
        return head;
}

 反转链表

思路:由题目介绍可以知道本题要求我们改变链表中各结点的指向,即将结点指向翻转过来。如下图。

为实现上述改变,我们首先考虑到用两个指针,用n1代表空,头结点为n2,使n2指向n1,即使原来的头指向NULL变成了尾结点。但是这个时候会造成一个问题,当我们想通过n2往后走找到2结点时,1和2已经失去了连接无法找到结点2如下图。所以我们考虑用三个指针,两个指针n1与n2用于反转,n3则用于保存结点的位置。

如下图,使用三个指针进行链表的反转。用n3保存n2->next的结点位置 。

当三个指针处于如下图状态时,停止移动。

实现代码如下。 

struct ListNode* reverseList(struct ListNode* head) {
    if(head ==NULL)
    {
        return NULL;
    }
    struct ListNode*n1 = NULL;
    struct ListNode*n2 = head;
    struct ListNode*n3 = n2->next;

    while(n2)//n2为空时停止移动
    {
       n2->next = n1;//反转链表指向
        n1 = n2;
        n2 = n3;
        if(n3)//n3会先走到空,当n3=NULL时无法进行移动。
        n3 = n3->next;
    }
    return n1;
    
}

总结

在做有关链表相关题目时,一定要进行图像的分析!!!其次所有有关链表的问题,要对链表是否为空、链表是否只有一个头结点进行分析。有关链表的合并通常直接开辟新的链表更加快捷方便。在后续的文章中,我还为问题的很多的小明同学分享有关单链表的题目,关注我,细听下回分解。

  • 15
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 一本通 OJ 库的测试数据,通常是用来验证提交的代码在各种情况下的正确性。测试数据可以分为两种类型,手动和自动。 手动测试数据是由目的出人根据意和数据范围设计的一组数据,用来检测程序的正确性和运行效率。手动测试数据的优点是能够涵盖各种情况,但缺点是数量相对较少,不足以覆盖所有可能的情况。 自动测试数据是由程序自动生成的一组数据,可以生成大量的数据以检测程序的健壮性和效率。自动测试数据的优点是数量大且可以自动生成,但缺点是可能无法覆盖某些特殊情况,导致漏洞。 对于提交的代码,一本通 OJ 库会对其进行编译和运行,然后与测试数据进行比较,判断代码的正确性和效率。如果代码通过了测试数据,就会被判定为正确,否则会被判定为错误,并给出具体的错误信息,供用户进行调试和改进。 综上所述,一本通 OJ 库的测试数据是一个重要的组成部分,它可以帮助用户测试代码的正确性和运行效率,提高用户的编程技能,同时也可以帮助出人设计更好的目,并保证目的质量和难度。 ### 回答2: 一本通 oj库是一个在线的程序设计竞赛平台,提供了丰富的编程目和测试数据。测试数据是用于对程序进行测评的输入和输出数据集合。在目描述中,会对问进行详细的解释和要求,并提供多组测试数据作为样例,让程序员运行他们的代码,并得到程序的输出结果。 测试数据通常包括正向测试数据和反向测试数据。正向测试数据是指符合目条件的测试数据,覆盖了大多数情况,测试程序是否正确;而反向测试数据则是用于测试程序是否能够正确处理异常情况。 在使用一本通 oj库时,程序员不仅需要通过编写算法和程序的方式解决问,还需要通过分析测试数据来判断自己的代码是否正确。而一本通 oj库的丰富数据集合为程序员提供了充足的测试数据,帮助程序员准确地检测代码中存在的漏洞和错误。 总之,一本通 oj库提供了全面的测试数据来测试程序员的代码是否满足目描述和要求,是程序员进行程序设计竞赛、算法练习和编程学习的良好平台。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值