单链表经典oj题(2)

前言

这次将要把剩下的oj题将以图解和自己的理解把它讲解完,希望对大家有所帮助,这次的讲解也是干货

第一题

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

ok这次就简单点,大家自己去看题目了

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

暴力思路

想想看不考虑空间和时间的消耗,什么代码最容易想

两个链表,可不可以直接把两个链表的值放在一个数组中

然后再排序,当然这里的链表大小是有序的,放在数组中时

可以判断大小,从而不用去排序

再根据数组自行去malloc一个链表,是不是非常暴力的思路

这个暴力代码其实也很重要,至少是算法小白入门的绝招

#include<stdio.h>
#include<stdlib.h>
typedef struct SlistNode {struct SlistNode* next;int val;
}SLNode,*SL;
SLNode* Buyslistnode(int data)
{SL newnode = (SL)malloc(sizeof(SLNode));newnode->next = NULL;newnode->val = data;return newnode;
}
SL initlist1()
{SL list1 = (SL)malloc(sizeof(SLNode));list1->val = 1;list1->next = Buyslistnode(2);list1->next->next = Buyslistnode(4);return list1;
}
SL initlist2()
{SL list2 = (SL)malloc(sizeof(SLNode));list2->val = 1;list2->next = Buyslistnode(3);list2->next->next = Buyslistnode(4);return list2;
}
int cmp(const void* p1, const void* p2)
{return *(int*)p1 - *(int*)p2;
}
void text1()
{//我们这里直接考虑list1与list2都不是空链表的情况//其实其他的情况可以通过if判断排除//初始化题目//list1   1->2->4//list2   1->3->4SL list1 = initlist1();SL list2 = initlist2();//题目中链表的结点数是0~50//所以直接可以用静态数组int newarr[110];int size = 0;while (list1){newarr[size++] = list1->val;list1 = list1->next;}while (list2){newarr[size++] = list2->val;list2 = list2->next;}qsort(newarr, size, sizeof(int), cmp);SL phead = (SL)malloc(sizeof(SLNode));SL cur = phead;for (int i = 0; i < size; i++){cur->next = Buyslistnode(newarr[i]);cur = cur->next;}//至此已经完成//打印看结果吧cur = phead->next;while (cur){printf("%d ", cur->val);cur = cur->next;}
}
int main()
{text1();return 0;
}

那么看结果

OK接下来看看优化的思路 头结点+双头插

对于这个例子

我们一第二条链表为基础对他进行插入操作

我们使用两个指针,分别指向两条链表的第一个位置cur1 cur2

如果第一个链表的值小于第二个链表的值那么尾插到此时第二个链表指针的前面

cur1->val<=cur2->val      

并且让第一个指针cur1=cur1->next;

当然这里只是大题思路不是代码

如果大于 cur1->val>cur2->val   

那么让cur2=cur2->next

在进行操作的时候,我们为了避免在第一个位置插入 ,从而加入了头指针

OK,看代码呗

struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {if(list1==NULL&&list2==NULL)return list1;else if(list1!=NULL&&list2==NULL)return list1;else if(list1==NULL&&list2!=NULL)return list2;struct ListNode*p1=list1;struct ListNode*p2=list2;struct ListNode*p2head=(struct ListNode*)malloc(sizeof(struct ListNode));p2head->next=p2;struct ListNode*front=p2head;while(p1&&p2){if(p1->val<=p2->val){//双指针中间插入//front->next=p1;struct ListNode*temp=p1;p1=p1->next;temp->next=p2;front=temp;}else{front=p2;p2=p2->next;}}//如果p2==null此时p1不为空,把p1接起来if(p2==NULL)front->next=p1;return p2head->next;}

 第二题

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

链表分割_牛客题霸_牛客网 (nowcoder.com)

ok

这个题目其实也可以暴力

但是

已经写了好多次暴力了,对吧

这一次可以说说思路

仍然可以使用数组,然后直接排序,不管x为多少,按从小到大的顺序,没有错

然后构建链表,这个题目就完了

挺暴力的吧

可以的

但是这个代码和之前大差不差

直接来看具体的思路

我们可以把一个链表分成两个链表,list1一个是大于等于x的,list2一个是小于x的

最后让list2连接list1

就完成任务了

思路看起来简单但是细节还是很多

我们在代码中有注释

class Partition {
public:ListNode* partition(ListNode* pHead, int x) {if(pHead==NULL&&pHead->next==NULL)return pHead;auto *head=(ListNode*)malloc(sizeof(ListNode));head->next=pHead;//头结点ListNode*front=head;ListNode*newlist=NULL;ListNode*newtail=NULL;ListNode*p=pHead;while(p){if(p->val<x){//在原有的链表上去除小于x的值ListNode*temp=p;p=p->next;temp->next=NULL;front->next=p;//对新的链表操作//小于x的值重新连成一个链表if(newlist==NULL){newlist=newtail=temp;}else{newtail->next=temp;newtail=temp;}}else {front=p;p=p->next;  }}//不要忘了呀,新的链表有可能为空呀,哎呦,搞了个半天if(newtail==NULL)return pHead;elsenewtail->next=head->next;return newlist;}
};

这个题目思路还是不难,继续努力

第三题

链表的回文结构_牛客题霸_牛客网 (nowcoder.com)

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

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

1->2->2->1
返回:true

这个题目有难度了

所以我们可以通过画图来理解一下

思路,

我们可以找到中间的结点,把中间的结点逆置过来

然后一个指针从中间

另一个指针从开头

一直判断他们是否相等,就可以得到答案

看图呗

 OK,找中以及逆转链表之前已经有过讲解了

单链表的经典oj题(1)-CSDN博客

好吧,不懂可以去看

我们现在直接去看代码喽

 ListNode*middle(ListNode*A){ListNode*slow=A;ListNode*fast=A;while(fast&&fast->next){fast=fast->next->next;slow=slow->next;}return slow;}ListNode* revearse(ListNode*src){ListNode* cur=src;ListNode* prev=NULL;while(cur){ListNode* temp=cur->next;cur->next=prev;prev=cur;cur=temp;}return prev;}bool chkPalindrome(ListNode* A) {// write code hereListNode*cur=middle(A);ListNode* tail=revearse(cur);while(A&&tail){if(tail->val!=A->val)return false;tail=tail->next;A=A->next;}return true;}

第四题

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

题目在这里

160. 相交链表 - 力扣(LeetCode)

OK

思路

 首先要判断他们是否是有相交节点

OK可以让他们走到最后一个节点

如果他们的最后一个节点相等,那他们就有相交节点,那么问题来了

怎么找到节点呢

要是知道两个链表的长度,再利用相对位移让他们距离相交节点的位移一样

最后让他们同时走,再判断,直到相等即可

OK

看代码

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {struct ListNode*A =headA;struct ListNode*B =headB;//这里最后一个节点没有加上,所以初始为1int sizeA=1;int sizeB=1;while(A->next){A=A->next;sizeA++;}while(B->next){B=B->next;sizeB++;}if(A!=B)return NULL;//通过假设,来简化代码//总之就是让A最长if(sizeA<sizeB){A=headB;B=headA;}else{A=headA;B=headB;}int abs=sizeA-sizeB>0?sizeA-sizeB:sizeB-sizeA;//使他们里相交点的距离相等while(abs--){A=A->next;}while(A!=B){A=A->next;B=B->next;}return B;
}

第五题 

 141. 环形链表 - 力扣(LeetCode)

题目

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

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

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

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点

OK

这个题目的思路很重要,我这里有两种做法

暴力求解

如果只要求求出题目,那么我们可不可以用一个数据来标明这个节点走过没有

  • -10^5 <= Node.val <= 10^5

当我们走过一个结点

直接给他加上一个10^6+10

+10是防止特殊情况,那么只要遍历一遍,走到某个节点,如果它大于

10^5证明我们走过这里,但是此时又回到了这里,此时可以判断为有环

缺点是破坏了链表

bool hasCycle(struct ListNode *head) {while(head){if(head->val>1e5)return true;else{head->val+=1e6+10;}head=head->next;}return false;
}

这种办法还是挺有意思的不是吗?

OK

来看看不改变链表的结构的写法吧

这个还是要画图理解,并且这里还是涉及到了相对位置的概念

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

话不多说下一题

第六题

142. 环形链表 II - 力扣(LeetCode)

 这个题目,是上个题目的升级版

OK看题

给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

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

不允许修改 链表。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

思路

大家看这里就是不允许修改链表了

这该如何是好

还是画图吧

这个题目更是一个物理的模型

OK,看代码吧

struct ListNode *detectCycle(struct ListNode *head) {struct ListNode*slow=head;struct ListNode*fast=head;struct ListNode*meet=NULL;struct ListNode*find=head;while(fast&&fast->next){fast=fast->next->next;slow=slow->next;if(fast==slow){meet=slow;break;}}if(meet==NULL)return NULL;while(find!=meet){find=find->next;meet=meet->next;}return find;
}

总结

今天的题还是挺多的,好好练吧

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

带有-i选项的sed命令在Linux上执行成功,但在MacOS上失败了

问题&#xff1a; 我已经成功地使用以下 sed 命令在Linux中搜索/替换文本&#xff1a; sed -i s/old_string/new_string/g /path/to/file然而&#xff0c;当我在Mac OS X上尝试时&#xff0c;我得到&#xff1a; command i expects \ followed by text我以为我的Mac运行的是…

未授权访问:Memcached 未授权访问漏洞

目录 1、漏洞原理 2、环境搭建 3、未授权访问 防御手段 今天继续学习各种未授权访问的知识和相关的实操实验&#xff0c;一共有好多篇&#xff0c;内容主要是参考先知社区的一位大佬的关于未授权访问的好文章&#xff0c;还有其他大佬总结好的文章&#xff1a; 这里附上大…

如何在OpenWrt软路由中增加一个新功能

为了在OpenWrt中增加一个新的功能&#xff0c;并使其支持 UCI 配置&#xff0c;我们可以创建一个简单的C语言服务&#xff0c;例如一个简单的日志服务。此服务将记录到日志文件中&#xff0c;并支持通过 UCI 配置启用或禁用日志功能。以下是详细的步骤和代码示例。 1 创建服务…

K8S三 K8S部署微服务应用

一 用k8s部署微服务应用 以我们之前用docker部署过的eureka应用为例&#xff0c;首先添加配置文件eureka-app-deployment.yaml用于创建Deployment apiVersion: apps/v1 kind: Deployment metadata:name: eureka-app-deployment # deployment名字labels:app: eureka-app spec:…

【C++】CentOS环境搭建-升级CMAKE

【C】CentOS环境搭建-升级CMAKE CMAKE报错CMake 3.12 or higher is required. You are running version 2.8.12.2升级步骤1.移除当前的cmake2.安装必要的构建工具和库3.下载最新的cmake源码并解压5.编译和安装6.验证安装 CMAKE报错CMake 3.12 or higher is required. You are r…

oraclesql中删除表中重复行的方法

在Oracle SQL中&#xff0c;删除表中的重复行有几种常见的方法。以下是其中的三种&#xff1a; 使用ROWID: 通过比较ROWID&#xff0c;你可以找到并删除重复的行。这是因为ROWID是Oracle数据库为每一行数据分配的唯一标识符。 sql DELETE FROM persons p1 WHERE ROWID NOT…

MySQL存储引擎详解

存储引擎 MySQL体系结构 连接层&#xff1a;与客户端连接&#xff0c;权限校验、连接池服务层&#xff1a;SQL接口和解析、查询优化、缓存、函数引擎层&#xff1a;索引、存储引擎存储层&#xff1a;系统文件、日志&#xff08;Redo、Undo等&#xff09; 存储引擎介绍 不同的…

SSH:安全远程访问的基石

SSH&#xff1a;安全远程访问的基石 一、引言 在当今这个数字化、网络化的时代&#xff0c;远程访问和管理计算机资源已成为日常工作的重要组成部分。然而&#xff0c;如何在不安全的网络环境中确保数据传输的机密性、完整性和可靠性&#xff0c;成为了一个亟待解决的问题。S…

前端测试策略与实践:单元测试、E2E测试与可访问性审计

前端测试策略是确保Web应用程序质量、性能和用户体验的关键组成部分。有效的测试策略通常包括单元测试、端到端&#xff08;E2E&#xff09;测试以及可访问性审计等多个层面。以下是关于这三类测试的策略与实践建议&#xff1a; 单元测试 定义与目的&#xff1a; 单元测试是针…

P2622 关灯问题

小小注解&#xff1a; 1. vis&#xff1a;表示到达该状态的步数&#xff08;min&#xff09;1&#xff0c; 因为我们是从开始状态 穷举&#xff0c;所以每次到一个新状态&#xff08;之前没有到过的状态&#xff09;就是最小步数。 如何判断是否是一个新状态呢&#xff0c…

axios常用配置

Axios 是一个基于 promise 的 HTTP 库&#xff0c;广泛用于浏览器和 node.js 中。以下是一些 Axios 常用的配置选项&#xff1a; url: 字符串&#xff0c;请求的服务器URL&#xff0c;是必填项。method: 请求方法&#xff0c;如 ‘get’, ‘post’, ‘put’, ‘delete’ 等&am…

免费远程控制软件哪个好用

免费远程控制软件哪个好用 在现今高度信息化的社会&#xff0c;远程控制软件已成为许多用户进行远程办公、技术支持和教育培训的重要工具。市面上有许多免费的远程控制软件&#xff0c;但哪款才是最好用的呢&#xff1f;本文将为您介绍几款热门的免费远程控制软件&#xff0c;…

Tab菜单与下拉式菜单

Tab菜单 利用CSS隐藏或显示栏目中的部分内容&#xff0c;实际Tab面板包含的全部内容都已下载到客户端浏览器当中。一般Tab面板仅显示一个Tab菜单项&#xff0c;当用户点选对应的菜单选项之后&#xff0c;才会显示对应的内容。 <!DOCTYPE html> <html><head>…

Matlab: ode45解微分方程——以弹簧振子模型为例

简介&#xff1a; 在科学和工程中&#xff0c;我们经常遇到描述事物变化的微分方程。这些方程可以帮助我们理解从行星运动到药物在体内的扩散等各种现象。但是&#xff0c;很多微分方程非常复杂&#xff0c;手动求解几乎不可能。这时&#xff0c;我们就可以使用像 ode45这样的…

【DL】FocalLoss的PyTorch实现

【DL】FocalLoss的PyTorch实现 此篇不介绍FocalLoss的原理&#xff0c;仅展示PyTorch实现FocalLoss的两种方式。个人认为相关原理已在文章《FocalLoss原理通俗解释及其二分类和多分类场景下的原理与实现》中讲得很清晰&#xff0c;故此篇不再介绍。 方式一 同时计算一个batc…

【iOS】frame与bounds区别

文章目录 前言framebounds两者区别size的区别总结 前言 在学习响应者链的过程中用到了frame与bounds的混用&#xff0c;这两个属性经常出现在我们的开发中&#xff0c;特别撰写一篇博客分析区别 首先&#xff0c;我们来看一下iOS特有的坐标系&#xff0c;在iOS坐标系中以左上…

C语言如何查看进程中环境变量中所有的值

示例代码&#xff1a;查看进程中环境变量中所有的值。 #include <stdio.h>int main(){extern char** environ;for (char** pp environ; *pp; pp){printf("%s\n", *pp);}return 0; }输出结果&#xff1a; SHELL/bin/bash WSL2_GUI_APPS_ENABLED1 WSL_DISTRO_…

【debug】如何使用pycharm对代码调试

后续会将所有debug中遇到的知识放入&#xff0c;建议关注收藏 本站友情链接&#xff1a; 基本理论专栏&#xff08;当前更新好的debug所有内容都在这里&#xff09; 【debug】报错解决方法&#xff08;CondaHTTPError&#xff1a;HTTP 000 connection failed for url&#xff…

【回溯 状态压缩 深度优先】37. 解数独

本文涉及知识点 回溯 状态压缩 深度优先 LeetCode37. 解数独 编写一个程序&#xff0c;通过填充空格来解决数独问题。 数独的解法需 遵循如下规则&#xff1a; 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只…

leetCode刷题记录4-面试经典150题-2

文章目录 不要摆&#xff0c;没事干就刷题&#xff0c;只有好处&#xff0c;没有坏处&#xff0c;实在不行&#xff0c;看看竞赛题面试经典 150 题 - 2210. 课程表 II 不要摆&#xff0c;没事干就刷题&#xff0c;只有好处&#xff0c;没有坏处&#xff0c;实在不行&#xff0c…