【数据结构】面试OJ题——链表
目录
1.移除链表元素
思路:
2.反转链表
思路:
3.链表的中间结点
思路:
4.链表中的倒数第K个结点
思路:
5.合并两个有序链表
思路:
6.链表分割
思路:
7.链表的回文结构
思路:
8.随机链表的复制
思路:
1.移除链表元素
203. 移除链表元素 - 力扣(LeetCode)
给你一个链表的头节点
head和一个整数val,请你删除链表中所有满足Node.val == val的节点,并返回 新的头节点 。

思路:
定义新链表的头结点和尾结点,循环遍历原链表即可,遇到复合的结点删除即可;
最后将尾结点的next置空。
因为这里并没有使用哨兵位,所以第一次插入的时候,要特殊处理
struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode* newnode = NULL,*tail = NULL;struct ListNode* cur = head;while(cur){//if(cur->val != val){//空,尾插if(tail == NULL){newnode = tail = cur;}else{tail->next = cur;tail = tail->next;}cur = cur->next;}else{struct ListNode* tmp = cur;cur = cur->next;free(tmp);tmp = NULL;}}if(tail)tail->next = NULL;return newnode;
}
2.反转链表
206. 反转链表 - 力扣(LeetCode)
给你单链表的头节点
head,请你反转链表,并返回反转后的链表。

思路:
定义三指针,当前位置,上一个位置,下一个位置;
将结点next链接到上一个结点即可,然后将下一个位置赋给当前指针;


struct ListNode* reverseList(struct ListNode* head) {struct ListNode* cur = head;struct ListNode* prev = NULL;while(cur){struct ListNode* next = cur->next;cur->next = prev;prev = cur;cur = next;} return prev;
}
3.链表的中间结点
876. 链表的中间结点 - 力扣(LeetCode)
给你单链表的头结点
head,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
思路:
使用快慢指针方式,快指针走两步,慢指针走一步,可以发现当快指针为NULL 或者快指针的下一个为空的时候 slow是中间结点


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;
}
4.链表中的倒数第K个结点
链表中倒数第k个结点_牛客题霸_牛客网 (nowcoder.com)
输入一个链表,输出该链表中倒数第k个结点。

思路:
一般链表问题,使用最多的解决方式就是快慢指针,这个题目和第三题相似很多;
先让快指针走K步,然后两指针同时走;
注:这里的快指针和慢指针一起走 是一步步走;同时,防止快指针走K步越界了,


struct ListNode* FindKthToTail(struct ListNode* pListHead, int k ) {//快慢指针struct ListNode* fast = pListHead;struct ListNode* slow = pListHead;//快指针先走k步while(k--){if(fast == NULL)return NULL;fast = fast->next;}//同时走while(fast){fast = fast->next;slow = slow->next;}return slow;
}
5.合并两个有序链表
21. 合并两个有序链表 - 力扣(LeetCode)
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

思路:
合并两个链表按照大小顺序排列,尾插小的结点;
第一次:将走完链表其中一条,注意并没有定义哨兵位,所以第一次插入特殊处理
第二次:将没走完的链表直接尾插到新链表后即可;
将小的结点尾插到新链表中


struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {struct ListNode* newnode = NULL,*tail = NULL;if(list1 == NULL)return list2;if(list2 == NULL)return list1;while(list1 && list2){if(list1->val < list2->val){if(newnode == NULL){newnode = tail = list1;}else{tail->next = list1;tail = tail->next;}list1 = list1->next;}//list2else{if(newnode == NULL){newnode = tail = list2;}else{tail->next = list2;tail = tail->next;}list2 = list2->next;}}if(list1)tail->next = list1;if(list2)tail->next = list2;return newnode;
}
6.链表分割
链表分割_牛客题霸_牛客网 (nowcoder.com)
现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。

思路:
对于链表分割最好用带头哨兵位的链表来解决,减化了两条链表的链接问题;如果不用哨兵位,要增加很多特殊处理判断;
有了哨兵位,在链接两条链表时,直接链接即可,尾部置NULL;
ListNode* partition(ListNode* phead, int x) {struct ListNode* cur = phead;struct ListNode* list1,*tail1,*list2,*tail2;//哨兵位list1 = tail1= (struct ListNode*)malloc(sizeof(struct ListNode));list2 = tail2= (struct ListNode*)malloc(sizeof(struct ListNode));while(cur){if(cur->val < x) //小于x{tail1->next = cur;tail1 = tail1->next;}else //大于等于x{tail2->next = cur;tail2 = tail2->next;}cur = cur->next;}tail1->next = list2->next; //链接两条链表tail2->next = NULL; //尾部置NULLphead = list1->next;free(list1);free(list2);return phead;}
7.链表的回文结构
链表的回文结构_牛客题霸_牛客网 (nowcoder.com)
对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。
给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

思路:
1.先用快慢指针找到中间结点
2.反转中间节点后的链表
3.是否为回文判断
bool chkPalindrome(ListNode* head) {//快慢指针找到中间节点struct ListNode* slow = head,*fast = head;while(fast && fast->next){fast = fast->next->next;slow = slow->next;}//此刻slow 是中间节点//反转mid后的链表struct ListNode* mid = slow; struct ListNode* cur = mid;struct ListNode* newnode = NULL;while(cur){struct ListNode* next = cur->next;cur->next = newnode;newnode = cur;cur = next;}//回文比较struct ListNode* phead = head;while(phead && newnode){if(phead->val != newnode->val)return false;phead = phead->next;newnode = newnode->next;}return true;}
8.随机链表的复制
138. 随机链表的复制 - 力扣(LeetCode)
给你一个长度为
n的链表,每个节点包含一个额外增加的随机指针random,该指针可以指向链表中的任何节点或空节点。构造这个链表的 深拷贝。 深拷贝应该正好由
n个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的next指针和random指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
思路:
1.先复制一条没有random的新链表,每个节点尾插到对应结点后面
2.添加random,可以发现,复制的结点的上一个结点的random就是该结点需要的random
3.将添加后的链表尾插到新链表中,记得跳过原链表的结点
struct Node* copyRandomList(struct Node* head) {struct Node* cur = head;while(cur){struct Node* newnode = (struct Node*)malloc(sizeof(struct Node));newnode->val = cur->val;newnode->next = cur->next;cur->next = newnode;cur = cur->next->next;}//添加randomcur = head;while(cur){struct Node* copy =cur->next;//原链表 random为空情况if(cur->random == NULL){copy->random = NULL;}else{copy->random = cur->random->next;}cur = cur->next->next;}//尾插cur = head;struct Node* newnode = NULL,*tail = NULL;while(cur){struct Node* copy =cur->next;struct Node* next = copy->next;;if(tail == NULL){newnode = tail = copy;}else{tail->next = copy;tail = tail->next;}cur->next = next;cur = next;}return newnode;
}


相关文章:
【数据结构】面试OJ题——链表
目录 1.移除链表元素 思路: 2.反转链表 思路: 3.链表的中间结点 思路: 4.链表中的倒数第K个结点 思路: 5.合并两个有序链表 思路: 6.链表分割 思路: 7.链表的回文结构 思路: 8.随机链表…...
flask web开发学习之初识flask(三)
文章目录 一、flask扩展二、项目配置1. 直接配置2. 使用配置文件3. 使用环境变量4. 实例文件夹 三、flask命令四、模版和静态文件五、flask和mvc架构 一、flask扩展 flask扩展是指那些为Flask框架提供额外功能和特性的库。这些扩展通常遵循Flask的设计原则,易于集成…...
【设计模式-3.1】结构型——外观模式
说明:本文介绍设计模式中结构型设计模式中的,外观模式; 亲手下厨还是点外卖? 外观模式属于结构型的设计模式,关注类或对象的组合,所呈现出来的结构。以吃饭为例,在介绍外观模式之前࿰…...
flutter学习-day2-认识flutter
📚 目录 简介特点架构 框架层引擎层嵌入层 本文学习和引用自《Flutter实战第二版》:作者:杜文 1. 简介 Flutter 是 Google 推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。开发者可以通过 Dart 语言开发 App&#…...
解决selenium使用.get()报错:unknown error: unsupported protocol
解决方法 将原来的: url "https://www.baidu.com" browser.get(url)替换为: url "https://www.baidu.com" browser.execute_script(f"window.location.replace({url});") # 直接平替 .get()问题解析 之前运行都是正…...
关于加密解密,加签验签那些事
面对MD5、SHA、DES、AES、RSA等等这些名词你是否有很多问号?这些名词都是什么?还有什么公钥加密、私钥解密、私钥加签、公钥验签。这些都什么鬼?或许在你日常工作没有听说过这些名词,但是一旦你要设计一个对外访问的接口ÿ…...
容器重启后,Conda文件完整保存(虚拟环境、库包),如何重新安装conda并迁移之前的虚拟环境
Vim安装 容器重启后默认是vi,升级vim,执行命令 apt install -y vim安装 Anaconda 1. 下载Anaconda 其他版本请查看Anaconda官方库 wget https://mirrors.bfsu.edu.cn/anaconda/archive/Anaconda3-2023.03-1-Linux-x86_64.sh --no-check-certificate…...
gitee对接使用
1.创建一个文件夹 2.进入Gitee接受对方项目编辑 3.打开终端初始化一开始创建的文件夹 git init 3.1打开终端 3.2输入git.init 4.克隆对方的项目 4.1进入Gitee复制对方项目的路径 4.2在编辑器终端内克隆对方项目 git clone 网址 如此你的编辑器就会出现对方的项目 …...
C语言中的一维数组与二维数组
目录 一维数组数组的创建初始化使用在内存中的存储 二维数组创建初始化使用在内存中的存储 数组越界 一维数组 数组的创建 数组是一组相同类型元素的集合。 int arr1[10]; char arr3[10]; float arr4[10]; double arr5[10];下面这个数组能否成功创建? int count…...
【Linux】地址空间
本片博客将重点回答三个问题 什么是地址空间? 地址空间是如何设计的? 为什么要有地址空间? 程序地址空间排布图 在32位下,一个进程的地址空间,取值范围是0x0000 0000~ 0xFFFF FFFF 回答三个问题之前我们先来证明地址空…...
作为一个产品经理带你了解Axure的安装和基本使用
1.Axure的简介 Axure是一种强大的原型设计工具,它允许用户创建交互式的、高保真度的原型,以及进行用户体验设计和界面设计。Axure可以帮助设计师和产品经理快速创建和共享原型,以便团队成员之间进行沟通和反馈。Axure提供了丰富的交互组件和功…...
接口测试总结及其用例设计方法
接口测试的总结文档 第一部分:主要从问题出发,引入接口测试的相关内容并与前端测试进行简单对比,总结两者之前的区别与联系。但该部分只交代了怎么做和如何做?并没有解释为什么要做? 第二部分:主要介绍…...
2023团体程序设计天梯赛——模拟赛和总决赛题
M-L1-1 嫑废话上代码 Linux 之父 Linus Torvalds 的名言是:“Talk is cheap. Show me the code.”(嫑废话,上代码)。本题就请你直接在屏幕上输出这句话。 输入格式: 本题没有输入。 输出格式: 在一行中输出…...
智能优化算法应用:基于人工蜂鸟算法无线传感器网络(WSN)覆盖优化 - 附代码
智能优化算法应用:基于人工蜂鸟算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用:基于人工蜂鸟算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.人工蜂鸟算法4.实验参数设定5.算法结果6.参考…...
视频中自监督学习:「我的世界」下指令理解与跟随
本文介绍了北京大学人工智能研究院梁一韬助理教授所带领的 CraftJarvis 团队在「我的世界」环境下探索通用智能体设计的新进展,题为“GROOT: Learning to Follow Instructions by Watching Gameplay Videos”。 GROOT 该研究的核心目标是探索能否摆脱文本数据的标…...
Spring基于xml半注解开发
目录 Component的使用 依赖注解的使用 非自定义Bean的注解开发 Component的使用 基本Bean注解,主要是使用注解的方式替代原有的xml的<bean>标签及其标签属性的配置,使用Component注解替代<bean>标签中的id以及class属性,而对…...
功能测试,接口测试,自动化测试,压力测试,性能测试,渗透测试,安全测试,具体是干嘛的?
软件测试是一个广义的概念,他包括了多领域的测试内容,比如,很多新手可能都听说:功能测试,接口测试,自动化测试,压力测试,性能测试,渗透测试,安全测试等&#…...
oracle 下载java之前版本
登录oracle官网:Oracle | Cloud Applications and Cloud Platform 点击resource 进入该页面 点击这个 出现之前版本...
LLM之Agent(四)| AgentGPT:一个在浏览器运行的Agent
AgentGPT是一个自主人工智能Agent平台,用户只需要为Agent指定一个名称和目标,就可以在浏览器中链接大型语言模型(如GPT-4)来创建和部署Agent平台。 PS:目前agentGPT仅支持chatgpt模型,暂时不支持本地llm模…...
AGM离线下载器使用说明
AGM专用离线下载器示意图: 供电方式: 通过 USB 接口给下载器供电,跳线 JP 断开。如果客户 PCB 的 JTAG 口不能提供 3.3V 电源,或仅需烧写下载器,尚未连接用户 PCB 时,采用此种方式供电。 或者:…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
c++ 面试题(1)-----深度优先搜索(DFS)实现
操作系统:ubuntu22.04 IDE:Visual Studio Code 编程语言:C11 题目描述 地上有一个 m 行 n 列的方格,从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子,但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...
如何在看板中有效管理突发紧急任务
在看板中有效管理突发紧急任务需要:设立专门的紧急任务通道、重新调整任务优先级、保持适度的WIP(Work-in-Progress)弹性、优化任务处理流程、提高团队应对突发情况的敏捷性。其中,设立专门的紧急任务通道尤为重要,这能…...
浅谈不同二分算法的查找情况
二分算法原理比较简单,但是实际的算法模板却有很多,这一切都源于二分查找问题中的复杂情况和二分算法的边界处理,以下是博主对一些二分算法查找的情况分析。 需要说明的是,以下二分算法都是基于有序序列为升序有序的情况…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...
