【Hello Algorithm】链表相关算法题
本篇博客介绍: 介绍下链表相关的算法题
链表相关算法题
- 快慢指针
- 回文结构链表
- 将单向链表按某值划分为左边小,中间相等,右边大的形式
- 复制带随机指针的链表
链表相关的算法题其实都算不上难
我们真正要考虑的是一些边界问题 事实上链表题就是在锻炼我们的处理边界能力
其次我们要强调的一点是 在笔试和面试中 我们的解题思路是不同的
在笔试中我们一般追求快速解题 只需要考虑时间复杂度 (一般空间复杂度上不会卡你)
但是在面试中 我们必须要在保证时间复杂度的情况下考虑空间复杂度 因为面试官会根据你写出的代码来判断你对于这个问题真正理解多少 有没有达到要求
快慢指针
比如说现在题目要求我们找出一个链表的中点
常规的解法就是 我们数一下链表的长度是多少
数出链表的长度之后除以二 之后使用指针一步步遍历到中点位置即可
快慢指针法解决中点问题
我们可以设计两个指针 快指针和慢指针
慢指针每次走一步
快指针每次走两步
我们可以通过调整快慢指针谁先走来调整中点
当然其中也有一些边界问题 比如说空指针的引用需要注意
lc上原题的连接如下
链表的中间节点
C++代码如下
class Solution {
public:ListNode* middleNode(ListNode* head) {if (head -> next == nullptr){return head;}ListNode* slow = head;ListNode* fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;} return slow;}
};
此外 快慢指针还能解决链表第K个节点之类的问题 思路同上
回文结构链表
正读和反读都相同的字符序列为回文
比如说下面的这一行字符
1 2 3 2 1
这就是一个回文结构
但是如果我们改变下最后节点的值 变成
1 2 3 2 2
这就不是一个回文结构了
判断它是不是一个回文结构我们也有多种做法
如果是在笔试中 我们可以选择最简单的 使用一个栈结构去解
具体解法为
- 我们首先定义一个栈结构
- 从头开始遍历所有的链表值 将所有的链表值放到栈结构中
- 这样子我们就得到了一个逆序的链表值
- 于是我们只要再次从头开始遍历整个链表 并且与栈中的逆序值做对比即可
题目连接和代码表示如下
回文链表
class Solution {
public:bool isPalindrome(ListNode* head) {if (head->next == nullptr){return true;}stack<int> st;ListNode* cur = head;while(cur){st.push(cur->val);cur = cur->next;}cur = head;while(!st.empty()){if (st.top() == cur->val){st.pop();cur = cur->next;}else {return false;}}return true;}
};
但是上面的解法仅限于笔试中 如果在面试中我们遇到了这个问题肯定是面试官想考查我们空间复杂度为O1的解法
其实思路也很简单
- 找到链表的左中点 并且指向空
- 翻转整个链表的右半部分(以左中点为结束位置)
- 设置两个指针 分别从左右开始对比值 如果全部相同 最后返回true 反之返回false
- 最后一定要记得将链表复原
代码表示如下
class Solution {
public:bool isPalindrome(ListNode* head) {if (head->next == nullptr){return true;}// 0 设置返回值bool ret = true;// 1 找出链表的左中点ListNode* slow = head;ListNode* fast = head;while(fast->next && fast->next->next){fast = fast->next->next;slow = slow->next;}// 2 设置左右中点ListNode* leftmidpoint = slow; ListNode* rightmidpoint= slow->next; // 排除掉了一个节点的情况 不可能为空// 3 开始翻转ListNode* n1 = leftmidpoint;ListNode* n2 = rightmidpoint;ListNode* n3 = rightmidpoint->next; // 有可能为空leftmidpoint->next = nullptr;while(1){n2 ->next = n1;n1 = n2;n2 = n3;if (n3){n3 = n3->next;}else {break;}}ListNode* righthead = n1;ListNode* cur1 = head;ListNode* cur2 = righthead;while (cur1 != nullptr){if (cur1->val == cur2->val){cur2 = cur2->next;cur1 = cur1->next;}else{ret = false;break;}}// 4 还原链表 leftmidpoint->next = rightmidpoint;n1 = righthead;n2 = righthead->next;righthead->next = nullptr;if (n2 == leftmidpoint){return ret;}n3 = n2->next;while(1){ n2->next = n1;n1 = n2;n2 = n3;if (n3 == leftmidpoint){break;}else {n3 = n3->next;}}return ret;;}
};
将单向链表按某值划分为左边小,中间相等,右边大的形式
题目要求如下
链接:https://www.nowcoder.com/questionTerminal/04fcabc5d76e428c8100dbd855761778
来源:牛客网
给定一个链表,再给定一个整数 pivot,请将链表调整为左部分都是值小于 pivot 的节点,中间部分都是值等于 pivot 的节点, 右边部分都是大于 pivot 的节点。
除此之外,对调整后的节点顺序没有更多要求。
解题思路上其实没有难点
- 我们设置六个指针 分别是小头 小尾 等头 等尾 大头 大尾即可
- 之后遍历链表 更新上面的指针
- 最后让这些指针相连
- 有一个难点就是我们要考虑有区域为空的情况
代码表示如下
# include <bits/stdc++.h>
using namespace std;struct list_node{int val;struct list_node * next;
};
#define Node list_node
int pivot;list_node * input_list(void)
{int n, val;list_node * phead = new list_node();list_node * cur_pnode = phead;scanf("%d%d", &n, &pivot);for (int i = 1; i <= n; ++i) {scanf("%d", &val);if (i == 1) {cur_pnode->val = val;cur_pnode->next = NULL;}else {list_node * new_pnode = new list_node();new_pnode->val = val;new_pnode->next = NULL;cur_pnode->next = new_pnode;cur_pnode = new_pnode;}}return phead;
}
void insertHead(Node *head, Node* x) {if(x==NULL || head==NULL) return;Node* last = head->next;head->next = x;x ->next = last;
}list_node * list_partition(list_node * head, int pivot)
{//在下面完成代码if(head==NULL || head->next ==NULL)return head;Node dummy_head;list_node *first = head;list_node lt,gt,eq;Node *l = <,*g = >, *e = &eq;lt.next = gt.next = eq.next = NULL;while(first) {if(first ->val == pivot) {e ->next = first,first = first->next,e = e->next,e->next = NULL;}else if(first->val > pivot) {g ->next = first,first = first->next, g = g->next,g->next = NULL;}else {l->next = first,l = l->next,first = first->next, l->next = NULL;}}e->next = gt.next;l->next = eq.next;first = lt.next;while(first) {printf("%d ", first->val);first = first->next;}return lt.next;}int main ()
{list_node * head = input_list();list_partition(head, pivot);return 0;
}
复制带随机指针的链表
题目描述可以直接参考leetcode
我这里就不水字数了
复制随机指针的链表
这个题目在我刚刚接触C++的时候其实也做过一次 博客连接如下
复制带随机指针的链表
这个题目的难点其实只有一个
如何确定随机指针指向的位置 如果随机指针指向的位置一定是向后的话我们倒是可以使用数步数的方式来实现 可要是随机指针指向的是前面呢? 通过遍历去找嘛?
这样子时间复杂度直接上N方了 肯定是过不了的
那么我们解决这个难点的思路有两个
- 使用哈希表 哈希表的KEY值对应原节点 VALUE值对应复制的节点 这样子我们只要找到原来的节点的随机指针 再到哈希表中找对应的VALUE值即可
- 因为随机指针本质上就是指向该链表中的某一个节点 所以说只要我们能够确定该链表中任意一个节点的相对位置 我们就能够找到复制后的随机指针应该指向哪里 于是我们可以选择在原链表的每个节点后面加上一个复制的节点 这样子我们通过原链表的随机指针找到对应的节点后下一个节点就是我们复制节点的随机指针应该指向的节点了
这两种方法的时间复杂度都是O(N) 但是第一种方法的空间复杂度要高一些
所以说我们在面试中要选用第二种方法 在笔试中可以选择第一种方法
代码表示如下
class Solution {
public:Node* copyRandomList(Node* head) {if (head == nullptr){return nullptr;}// 1 复制节点到原节点后Node* cur = head;Node* NEXT = nullptr; // null?while (cur){NEXT = cur -> next;cur -> next = new Node(cur->val); cur -> next -> next = NEXT;cur = NEXT;}// 2 随机指针开始拷贝 Node* cur2 = head->next;cur = head;while(cur){cur2 = cur->next;if (cur->random){cur2->random = cur->random->next;}else {cur2->random = nullptr;}cur = cur->next->next;}// 3 分离出复制的节点cur2 = head->next;cur = head;NEXT = nullptr;Node* NEXT2 = nullptr;head = cur2;while(cur){NEXT = cur->next->next;if (NEXT== nullptr){NEXT2 = nullptr;}else {NEXT2 = NEXT->next;}cur->next = NEXT;cur2->next = NEXT2;cur = NEXT;cur2 = NEXT2;}return head;}
};
相关文章:
【Hello Algorithm】链表相关算法题
本篇博客介绍: 介绍下链表相关的算法题 链表相关算法题 快慢指针回文结构链表将单向链表按某值划分为左边小,中间相等,右边大的形式复制带随机指针的链表 链表相关的算法题其实都算不上难 我们真正要考虑的是一些边界问题 事实上链表题就是在…...
自动化管理管理工具----Ansible
目录 编辑 一、Ansible概念 1.1特点 二、工作机制(日常模块) 2.1 核心程序 三、Ansible 环境安装部署 四、ansible 命令行模块 4.1command 模块 4.2shell 模块 4.3cron 模块 4.4user 模块 4.5group 模块 4.6copy模块 4.7file模块 4.8ho…...
深入理解css3背景图边框
border-image知识点 重点理解 border-image-slice 设置的值将边框背景图分为9份,图像中间的舍弃,其他部分图像对应边框的相应区域放置,上右下左四角固定,border-image-repeat设置的是除四角外其他部分的显示方式。 截图来自菜鸟教…...
【rust/egui】(六)看看template的app.rs:TextEdit
说在前面 rust新手,egui没啥找到啥教程,这里自己记录下学习过程环境:windows11 22H2rust版本:rustc 1.71.1egui版本:0.22.0eframe版本:0.22.0上一篇:这里 TextEdit 文本编辑框 其定义为&#…...
Redis内存空间预估与内存优化策略:保障数据安全与性能的架构实践
推荐阅读 AI文本 OCR识别最佳实践 AI Gamma一键生成PPT工具直达链接 玩转cloud Studio 在线编码神器 玩转 GPU AI绘画、AI讲话、翻译,GPU点亮AI想象空间 资源分享 史上最全文档AI绘画stablediffusion资料分享 AI绘画关于SD,MJ,GPT,SDXL百科全书 「java、python面试题」…...
【zookeeper】zookeeper集群安装
环境规划 实际的生产使用中,我们一般推荐搭建奇数多节点的zookeeper集群,如3/5/7。在本次测试中,我使用了centos7 三台服务器搭建,复用了我搭建k8s集群的环境,如下表。 IPhostname192.168.2.140k8s-m1192.168.2.141k…...
CUDA小白 - NPP(2) - Arithmetic and Logical Operations(1)
cuda小白 原文链接 NPP GPU架构近些年也有不少的变化,具体的可以参考别的博主的介绍,都比较详细。还有一些cuda中的专有名词的含义,可以参考《详解CUDA的Context、Stream、Warp、SM、SP、Kernel、Block、Grid》 常见的NppStatus,…...
计算机视觉-LeNet
目录 LeNet LeNet在手写数字识别上的应用 LeNet在眼疾识别数据集iChallenge-PM上的应用 LeNet LeNet是最早的卷积神经网络之一。1998年,Yann LeCun第一次将LeNet卷积神经网络应用到图像分类上,在手写数字识别任务中取得了巨大成功。LeNet通过连续使用…...
Java 复习笔记 - 面向对象篇
文章目录 一,面向对象概述二,类和对象(一)类和对象的概述(二)定义类的补充注意事项 三,封装四,就近原则和this关键字(一)就近原则(二)…...
行业追踪,2023-08-31
自动复盘 2023-08-31 凡所有相,皆是虚妄。若见诸相非相,即见如来。 k 线图是最好的老师,每天持续发布板块的rps排名,追踪板块,板块来开仓,板块去清仓,丢弃自以为是的想法,板块去留让…...
科技资讯|苹果发布新专利:可在车内定位苹果的智能设备
根据美国商标和专利局近期公示的清单,苹果公司获得了一项名为《车内定位移动设备的系统和方式》专利,概述了在车内狭窄空间内如何定位 iPhone 等移动设备。 Find My 服务现阶段没有使用 UWB 来追踪 iPhone 或者 iPad,而是依赖 GPS 等相关辅…...
浅析Linux SCSI子系统:IO路径
文章目录 概述scsi_cmd:SCSI命令result字段proto_op字段proto_type字段 SCSI命令下发scsi_request_fnscsi_dev_queue_readyscsi_host_queue_ready SCSI命令响应命令请求完成的软中断处理 相关参考 概述 SCSI子系统向上与块层对接,由块层提交的对块设备的…...
linux系统(centos、Ubuntu、银河服务器)备份
制作u盘启动盘 下载usblive系统镜像 Get Kali | Kali Linux 下载u盘启动工具 balenaEtcher - Flash OS images to SD cards & USB drives 点击下载,等待下载完成 双击安装,等待安装完成 双击 启动 选择镜像 选择U盘 开始烧录 等地制作完成 进入…...
堆栈深度超过限制
报错:Cause: com.kingbase8.util.KSQLException: 错误: 堆栈深度超过限制 Hint: 在确定了平台的堆栈深度限制是足够大后,增加配置参数 "max_stack_depth"的值(当前值为2048kB).; 错误: 堆栈深度超过限制 Hint: 在确定了平台的堆栈深度限制是足…...
Linux ptrace系统调用
文章目录 一、ptrace 简介二、ptrace 参数request2.1 PTRACE_TRACEME2.2 PTRACE_PEEKTEXT, PTRACE_PEEKDATA2.3 PTRACE_PEEKUSER2.4 PTRACE_POKETEXT, PTRACE_POKEDATA2.5 PTRACE_POKEUSER2.6 PTRACE_GETREGS, PTRACE_GETFPREGS2.7 PTRACE_GETREGSET2.8 PTRACE_SETREGS, PTRACE…...
CSDN每日一练 |『贝博士发奖金』『Longest Continuous Increasing Subsequence』『最小差值』2023-09-01
CSDN每日一练 |『贝博士发奖金』『Longest Continuous Increasing Subsequence』『最小差值』2023-09-01 一、题目名称:贝博士发奖金二、题目名称:Longest Continuous Increasing Subsequence三、题目名称:最小差值一、题目名称:贝博士发奖金 时间限制:1000ms内存限制:25…...
二维数组创建方式比较
暑假跟着地质队去跑山了,到现在还没结束,今天休息的时候突然刷到了一篇关于C二维数组创建方面的文章,我觉得还是非常不错滴,就将其中提到的新方法和我已经使用过的三种方法进行了比较,发现该方法提高了二维数组的分配、…...
安达发|富士康科技集团利用自动排程APS软件打造智慧工厂
富士康科技集团作为全球领先的3C产品研发制造企业,近年来积极布局智能制造领域,通过引入先进的自动化排程系统(APS),成功打造了智慧工厂,提高了生产质量与效率,降低了生产成本。 富士康集团自2019年下半年提出在观澜厂区建立数字可…...
云计算在大数据分析中的应用与优势
文章目录 云计算在大数据分析中的应用云计算在大数据分析中的优势云计算在大数据分析中的示例未来发展和拓展结论 🎉欢迎来到AIGC人工智能专栏~云计算在大数据分析中的应用与优势 ☆* o(≧▽≦)o *☆嗨~我是IT陈寒🍹✨博客主页:IT陈寒的博客&…...
linux————ELK(日志收集系统集群)
目录 一、为什么要使用ELK 二、ELK作用 二、组件 一、elasticsearch 特点 二、logstash 工作过程 INPUT(输入) FILETER(过滤) OUTPUTS(输出) 三、kibana 三、架构类型 ELK ELKK ELFK ELFKK EFK 四、构建ELk集群…...
Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
Spark 之 入门讲解详细版(1)
1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室(Algorithms, Machines, and People Lab)开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目,8个月后成为Apache顶级项目,速度之快足见过人之处&…...
渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止
<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet: https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...
【机器视觉】单目测距——运动结构恢复
ps:图是随便找的,为了凑个封面 前言 在前面对光流法进行进一步改进,希望将2D光流推广至3D场景流时,发现2D转3D过程中存在尺度歧义问题,需要补全摄像头拍摄图像中缺失的深度信息,否则解空间不收敛…...
对WWDC 2025 Keynote 内容的预测
借助我们以往对苹果公司发展路径的深入研究经验,以及大语言模型的分析能力,我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际,我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测,聊作存档。等到明…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
基于Java Swing的电子通讯录设计与实现:附系统托盘功能代码详解
JAVASQL电子通讯录带系统托盘 一、系统概述 本电子通讯录系统采用Java Swing开发桌面应用,结合SQLite数据库实现联系人管理功能,并集成系统托盘功能提升用户体验。系统支持联系人的增删改查、分组管理、搜索过滤等功能,同时可以最小化到系统…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...
