顺序表链表OJ题(2)->【数据结构】

W...Y的主页 😊

代码仓库分享 💕


前言:

单链表的结构常常不完美,没有双向链表那么”优秀“,所以繁衍出很多OJ练习题。今天我们继续来look look数据结构习题。

下面就是OJ时间!!!

【链表中倒数第K个节点】——牛客网

OJ链接

描述

输入一个链表,输出该链表中倒数第k个结点。

示例1

输入:

1,{1,2,3,4,5}

返回值:

{5}

题目函数接口:

pListHead:目标链表。k:倒数第K个节点。


理论上我们可以先遍历一遍求出链表长度,然后创建一个指针使其走过(k-1)个元素即可找到链表中倒是第k个节点。

但是这道题我们要把时间复杂度降到最大,只能遍历一遍,我们该怎么应对?

我们可以创建两个指针(快慢)slow和fast,将fast先走k个节点,然后让fast与slow开始一块走,直到fast指向NULL停止,这时slow指向的节点就是我们需要倒数第k个节点!!!

这里的快慢指针所使用的是路程差,让fast先走k个就是让slow少走k个,所得到的节点就是倒数第k个节点。

代码演示:

struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {
    struct ListNode* slow = pListHead;
    struct ListNode* fast = pListHead;
    while(k--)
    {
        if(fast == NULL)
            return NULL;
        fast = fast->next;
    }
    while(fast)
    {
        slow = slow->next;
        fast = fast->next;
    }
    return slow;
}

【leetcode 21.合并两个有序链表】

OJ链接 

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

提示:

  • 两个链表的节点数目范围是 [0, 50]
  • -100 <= Node.val <= 100
  • l1 和 l2 均按 非递减顺序 排列

题目函数接口:

 list1:目标链表1。list2:目标链表2。


 这道题与上篇博客中合并顺序表思路大同小异,创建一个新节点,取小的尾插到节点后面即可。

我们可以创建两个指针head与tail,head记录新链表的头节点,tail记录新链表的尾节点。

代码演示:

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
    struct ListNode* cur = list1;
    struct ListNode* tal = list2;
    struct ListNode* head = NULL;
    struct ListNode* tail = NULL;
    if(list1 == NULL)
        return list2;
    if(list2 == NULL)
        return list1;
    while(tal && cur)
    {
        if(cur->val>=tal->val)
        {
            if(head == NULL)
            {
                head = tail = list2;
            }
            else
            {
                tail->next = tal;
                tail = tail->next;
            }
            tal = tal->next;
        }
        else
        {
            if(cur->val<tal->val)
            {
                if(head == NULL)
                {
                    head = tail = list1;
                }
                else
                {
                    tail->next = cur;
                    tail = tail->next;
                }
            }
            cur = cur->next;
        }
        
    }
    if(cur)
        tail->next = cur;
    if(tal)
        tail->next = tal;
    return head;
}

 注意:这种题我们就必须考虑完善,比如:一个链表为空,我们就应该考虑这种情况应该直接返回另一个链表即可。 

if(list1 == NULL)

        return list2;

if(list2 == NULL)
        return list1;

这四句就是考虑为空的情况的,所以我们做题必须全面!!!

 【CM11  链表分割】——牛客网

OJ链接

描述:

现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。

题目函数接口:

我们一看这个函数接口为c++,但是c++与c在这个函数中内容相同,所以使用c语言也是ok

pHead:目标链表。x:分割数。


我们先举个实际例子说清楚题目含义:【1 3 2 5 1】x = 3

我们就应该以3为分界线,将小于3的放在链表前面,大于等于3的放在链表后面且顺序不能改变,得到的顺序应该为:【1 2 1 3 5】。

那我们该如何实现呢?

我们可以创建两条链表,将小于x的放入链表1,大于等于x的放入链表2中,然后进行合并即可得到结果。

大致思路已经出炉,现在我们应该考虑一下细节该怎么处理。

两条链表我们应该选带哨兵位的还是不带哨兵位的?

哨兵位是为了我们更好的头插,一般情况下带不带哨兵位都可以,不使用哨兵位可以使用二级指针进行操作,效果是相同的。但是这道题是带哨兵位的链表简单些,因为有特殊情况,比如小于x的链表内容为空,如果我们我们进行合并,可能会丢失数据,所以我们得用很多if语句进行判断才行,但是有了哨兵位就不需要考虑这么多问题。

代码演示:

class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        ListNode*ghead = NULL;
        ListNode*gtail = NULL;
        ListNode*lhead = NULL;
        ListNode*ltail = NULL;
        ghead = gtail = (ListNode*)malloc(sizeof(ListNode));
        lhead = ltail = (ListNode*)malloc(sizeof(ListNode));
        ListNode*cur = pHead;
        while(cur)
        {
            if(cur->val < x)
            {
                ltail->next = cur;
                ltail = ltail->next;
            }
            else
            {
                gtail->next = cur;
                gtail = gtail->next;
            }
            cur = cur->next;
        }
     
        ltail->next = ghead->next;
        gtail->next = NULL;

        ListNode*head = lhead->next;
        free(lhead);
        free(ghead);
        return head;
    }
};

【OR36 链表的回文结构】——牛客网

OJ链接

描述:

对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。

给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

测试样例:

1->2->2->1

返回:true

题目函数接口:

 A:目标链表。


那什么是回文呢?

奇数回文:1->2->3->2->1  偶数回文:1->2->2->1

如果是数组,可以从后往前进行非常简单,但是这时链表,应该怎么办呢?

使用快慢指针找到链表的中间节点,将中间节点后面的链表内容反转,然后用两个指针,一个在中间节点处,一个在链表最开始出,进行移动比较,如果都相同则为回文结构,反之则不是回文结构。

代码演示:

class PalindromeList {
public:
struct ListNode* middleNode(struct ListNode* head){
    struct ListNode* fast = head;
    struct ListNode* slow = head;
    while(fast&&fast->next)
    {
        fast = fast->next->next;
        slow = slow->next;
    }
    return slow;
}
struct ListNode* reverseList(struct ListNode* head){
    struct ListNode* cur = head;
    struct ListNode*  newhead = NULL;
    while(cur)
    {
        struct ListNode* next = cur->next;
        cur->next = newhead;

        newhead = cur;
        cur = next;
    }
    return newhead;

}
    bool chkPalindrome(ListNode* A) {
        struct ListNode* mid = middleNode(A);
        struct ListNode* rmid = reverseList(mid);

        while(rmid && A)
        {
            if(rmid->val != A->val)
            {
                return false;
            }
            rmid = rmid->next;
            A = A->next;
        }
        return true;
    }
};

 此程序我们封装了两个函数,一个为寻找中间节点的函数,一个为链表反转函数。当我们反转链表后,我们不需要将中间节点的next重新连接,让其成为相交链表即可。

这样判断的长度也一样,不需要考虑何时停止。 

【leetcode 160.相交链表】

OJ链接 

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

图示两个链表在节点 c1 开始相交

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

自定义评测:

评测系统 的输入如下(你设计的程序 不适用 此输入):

  • intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0
  • listA - 第一个链表
  • listB - 第二个链表
  • skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数
  • skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数

评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。

题目函数接口:

headA:目标链表A。headB:目标链表B。


如何判断两个链表相交,因为单链表一个结构体中只有一个next节点存放下一个结构体,所以只需要判断尾节点地址是否相等即可。虽然我们找的不是最开始相交的点,但是这样的思想非常简便。 

首先按照前面思路,判断两个链表是否相交,如果不相交就没有做下去的必要了,直接返回NULL即可。但是如果有节点我们就要寻找起始节点位置。

两个相交链表是由一段不相交的与一段相交的组合一起的,两段链表不一样长的那一段一定在不相交的位置。所以我们可以让较长的链表先遍历两个链表长度之差个节点,这样两个链表就一样长了,再进行逐一比较即可找到起始相交节点!!!

那我们想要知道两个链表长度就可以再判断两个链表是否相交时进行计数,因为判断两个链表相交就是判断尾节点是否相等,就是要将两个链表全部遍历一遍,一举两得。

理论形成,实践开始:

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    int lena = 1;
    int lenb = 1;
    struct ListNode *cura = headA;
    struct ListNode *curb = headB;
    while(cura->next)
    {
        cura = cura->next;
         lena++;
    }
    while(curb->next)
    {
        curb = curb->next;
        lenb++;
    }
    if(cura != curb)
    {
        return NULL;
    }
    int gap = abs(lena-lenb);
    struct ListNode *llist = headA;
    struct ListNode *slist = headB;
    if(lena > lenb)
    {
       ;
    }
    else
    {
        llist = headB;
        slist = headA;
    }
    while(gap--)
    {
        llist = llist->next;
    }
    while(llist != slist)
    {
         llist = llist->next;
         slist = slist->next;
    }
    return llist;
}

【leetcode 141.环形链表】 

OJ链接

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

题目函数接口:

 head:目标链表。


什么是环形链表,我们最先见到过的就是循环列表: 

但其实环形链表还有很多:

向上面的我们都可以称作环形链表。

那我们应该怎样判断出链表为环形链表呢?

这里我们还是基于快慢指针进行,如同数学中的追及问题一样,如果在一个环形跑到中,两个人速度不同,但是快的人落后于慢的人,快的人总会追到慢的人。

我们创建两个指针fast与slow,s两个人都从开始进行,slow走一步,fast走两步,如果有环它们一定会进入环中进行追及。 代码演示:

bool hasCycle(struct ListNode *head) {
    struct ListNode *fast = head;
    struct ListNode *slow = head;
    while(fast && fast->next)
    {
         fast = fast->next->next;
        slow = slow->next;
        if(fast == slow)
        {
            return true;
        }
    }
    return false;
}

 以上是本次数据结构OJ题分享,感谢大家观看,三连支持一下博主,博主会干劲十足的!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/98895.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于MQTT协议的物联网关

随着工业领域的不断发展&#xff0c;数字化转型已经成为企业迈向未来的必由之路。在这个数字化浪潮中&#xff0c;HiWoo Box以其强大的功能和创新的设计&#xff0c;在工业物联网领域被越来越多的人所熟知。特别是其基于MQTT协议的物联网关能力&#xff0c;也为企业实现智能化数…

运动耳机需要具备哪些功能、挂耳式运动蓝牙耳机推荐

作为运动爱好者&#xff0c;长时间的运动很容易枯燥&#xff0c;所以我会选择佩戴耳机来缓解运动的枯燥感&#xff0c;一款好的运动耳机可以让运动变得更加激情&#xff0c;还可以更好的享受运动的乐趣。 但现在的运动耳机产品实在是五花八门&#xff0c;到底什么样的运动蓝牙耳…

html-dom核心内容--四要素

1、结构 HTML DOM (文档对象模型) 当网页被加载时&#xff0c;浏览器会创建页面的文档对象模型&#xff08;Document Object Model&#xff09;。 2、核心关注的内容&#xff1a;“元素”&#xff0c;“属性”&#xff0c;“修改样式”&#xff0c;“事件反应”。>四要素…

uni-app:允许字符间能自动换行(英文字符、数字等)

<template><view class"container"><!-- 这里是你的文本内容 -->{{ multilineText }}</view> </template><style> .container {word-break: break-all; } </style>例如&#xff1a; <template><view class"…

使用 Amazon Lambda 进行无服务器计算:云架构中的一场革命

引言 十年前,无服务器架构还像是痴人说梦。不再如此了! 有了 Amazon Lambda,我们现在可以建构和运行应用程序而不需要考虑服务器。云供应商会无缝地处理所有服务器的供应、扩展和管理。我们只需要关注代码。 这为云部署带来了前所未有的敏捷性、自动化和优化。但是,要发挥它的…

DC/DC开关电源学习笔记(二)开关电源的分类

&#xff08;二&#xff09;开关电源的分类 1.DC/DC类开关电源2.AC/DC变换器3.电路结构分类4.功率开关管分类5.电路拓扑分类 根据变换方式&#xff0c;电源产品有下列四大类&#xff1b; &#xff08;1&#xff09;&#xff1a;第一大类&#xff1a;AC/DC开关电源&#xff1b; …

JVM-性能优化工具 MAT

一、MAT下载和安装 1、概述 MAT&#xff08;Memory Analyzer Tool&#xff09;工具是一款功能强大的]ava堆内存分析器。可以用于查找内存泄漏以及查看内存消耗情况。MAT是基于Eclipse开发的&#xff0c;不仅可以单独使用&#xff0c;还可以作为插件的形式嵌入在Eclipse中使用…

XML—DTD、 Schema

目录 DTD是什么&#xff1f; DTD有什么用途&#xff1f; DTD与XML有什么联系&#xff1f; DTD原理图 外部DTD DTD文件book.dtd: 使用外部DTD文件的XML文件 PCDATA XML 文档构建模块 一、元素 1、元素声明 ①、有元素&#xff1a; ②、空元素&#xff1a; ③、ANY…

Java系列 | MJDK 如何实现压缩速率的 5 倍提升?

MJDK 是基于 OpenJDK 构建的美团 JDK 发行版。本文主要介绍 MJDK 是如何在保障 java.util.zip.* API 及压缩格式兼容性的前提下&#xff0c;实现压缩/解压缩速率提升 5-10 倍的效果。希望相关的经验能够帮助到更多的技术同学。 1 前言 2 数据压缩技术 3 压缩技术在 Java 中的…

Langchain使用介绍之outparser 和memory

上一篇博客中对Langchain中prompt进行了详细的介绍&#xff0c;此篇博客将介绍Langchain中的outparser和memory。当调用大模型生成内容时&#xff0c;返回的内容默认是string类型&#xff0c;这对于我们获取response中的某些内容信息可能会带来障碍&#xff0c;例如返回的内容本…

STM32 CUBEMX CAN通信数据发送失败原因分析

CAN通信是一种数据通信协议&#xff0c;用于在不同设备之间进行通信。它是一种高效的、实时的、可靠的、多主机的、串行通信系统&#xff0c;通常用于汽车电子、工业自动化等领域。CAN通信协议是由德国BOSCH公司于1986年引入&#xff0c;并在欧洲和日本广泛使用。CAN通信具有独…

C# char曲线控件

一、char曲线显示随机数数据 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Runtime.InteropServices; using System.Text; using System.Threading; using Syst…

任意文件读取

文章目录 渗透测试漏洞原理任意文件读取1. 任意文件读取概述1.1 漏洞成因1.2 漏洞危害1.3 漏洞分类1.4 任意文件读取1.4.1 文件读取1.4.2 任意文件读取1.4.3 权限问题 1.5 任意文件下载1.5.1 一般情况1.5.2 PHP实现1.5.3 任意文件下载 2. 任意文件读取攻防2.1 路径过滤2.1.1 过…

安达发|富士康科技集团利用自动排程APS软件打造智慧工厂

富士康科技集团作为全球领先的3C产品研发制造企业&#xff0c;近年来积极布局智能制造领域&#xff0c;通过引入先进的自动化排程系统(APS),成功打造了智慧工厂&#xff0c;提高了生产质量与效率&#xff0c;降低了生产成本。 富士康集团自2019年下半年提出在观澜厂区建立数字可…

W5100S-EVB-PICO进行UDP组播数据回环测试(九)

前言 上一章我们用我们的开发板作为UDP客户端连接服务器进行数据回环测试&#xff0c;那么本章我们进行UDP组播数据回环测试。 什么是UDP组播&#xff1f; 组播是主机间一对多的通讯模式&#xff0c; 组播是一种允许一个或多个组播源发送同一报文到多个接收者的技术。组播源将…

网络渗透day6-面试01

&#x1f609; 和渗透测试相关的面试问题。 介绍 如果您想自学网络渗透&#xff0c;有许多在线平台和资源可以帮助您获得相关的知识和技能。以下是一些受欢迎的自学网络渗透的平台和资源&#xff1a; Hack The Box: Hack The Box&#xff08;HTB&#xff09;是一个受欢迎的平…

华为数通方向HCIP-DataCom H12-821题库(单选题:161-180)

第161题 以下关于 URPF(Unicast Reverse Path Forwarding) 的描述, 正确的是哪一项 A、部署了严格模式的 URPF,也能够可以同时部署允许匹配缺省路由模式 B、如果部署松散模式的 URPF,默认情况下不需要匹配明细路由 C、如果部署松散模式的 URPF,如果需要检查默认路由,则…

ConsoleApplication17_2项目免杀(Fiber+VEH Hook Load)

加载方式FiberVEH Hook Load Fiber是纤程免杀&#xff0c;VEH是异常报错&#xff0c;hook使用detours来hook VirtualAlloc和sleep&#xff0c;通过异常报错调用实现主动hook 纤程Fiber的概念&#xff1a;纤程是比线程的更小的一个运行单位。可以把一个线程拆分成多个纤程&#…

骨传导耳机十大品牌怎么选,骨传导耳机十大品牌排行榜分享

作为一个拥有20多款骨传导耳机来说&#xff0c;我也算是资深的使用者了&#xff0c;在骨传导耳机刚开始兴起的时候&#xff0c;我就开始接触了&#xff0c;近几年越来越多的骨传导耳机品牌诞生&#xff0c;我也是入手了不少&#xff0c;所以也算是对骨传导耳机非常熟悉了&#…

网络有源号角(50W-100W)社区小区广播 工地语音播报,隧道广播,钢铁广播广播系统

网络有源号角&#xff08;50W-100W&#xff09;社区小区广播 工地语音播报&#xff0c;隧道广播&#xff0c;钢铁广播广播系统 SV-7042T 50W网络有源号角 SV-7042T是深圳锐科达电子有限公司的一款壁挂式网络有源号角&#xff0c;具有10/100M以太网接口&#xff0c;可将网络音…