数据结构——线性表(链表,力扣中等篇,增删查改)

文章目录

  • 一、增删查改
    • 1.1增(插入节点)
      • 1.1.1两数后插入公约数
      • 1.1.2循环有序链表的插入
    • 1.2删(移除节点)
      • 1.2.1删除已知的node节点【交换val值】
      • 1.2.2移除数组中已存在的节点【unordered_set】
      • 1.2.3删除和为0的节点【前缀和】
    • 1.3改(交换节点)
      • 1.3.1链表中的下一个最大节点
      • 1.3.2删除右侧有一个更大数值的节点
      • 1.3.3交换K和倒数第K个节点
      • 1.3.4合并0之间的节点
    • 1.4其他
      • 1.4.1链表组件
      • 1.4.2螺旋矩阵
      • 1.4.3临界值的距离

一、增删查改

1.1增(插入节点)

序号题目链接
1两数后插入公约数https://leetcode.cn/problems/insert-greatest-common-divisors-in-linked-list/description/?envType=problem-list-v2&envId=linked-list
2循环有序链表的插入https://leetcode.cn/problems/4ueAj6/description/?envType=problem-list-v2&envId=linked-list

1.1.1两数后插入公约数

在两个数A和B的中间插入A和B的公约数【公约数的值可以用gcd直接求】

//求最大公约数gcd
ListNode* insertGreatestCommonDivisors(ListNode* head) {if(head==nullptr || head->next==nullptr)return head;ListNode* p=head;while(p->next!=nullptr){ListNode* node=new ListNode(gcd(p->val,p->next->val));node->next=p->next;p->next=node;p=p->next->next;}return head;
}

1.1.2循环有序链表的插入

给定循环单调非递减列表中的一个点,写一个函数向这个列表中插入一个新元素 insertVal ,使这个列表仍然是循环升序的。
在这里插入图片描述

Node* insert(Node* head, int insertVal) {Node* node=new Node(insertVal);//创建新节点if(head==nullptr){node->next=node;return node;}if(head->next==head){head->next=node;node->next=head;return head;}Node* cur=head;Node* next=head->next;while(next != head){if(cur->val <= insertVal && insertVal <= next->val) break;if((cur->val > next->val) && (insertVal >= cur->val || insertVal <= next->val) )  break;cur=cur->next;next=next->next;}node->next=next;cur->next=node;return head;
}

1.2删(移除节点)

序号题目链接
1删除链表中值为val的节点(简单)https://leetcode.cn/problems/remove-linked-list-elements/description/?envType=problem-list-v2&envId=linked-list
2删除已知的node节点https://leetcode.cn/problems/delete-node-in-a-linked-list/description/?envType=problem-list-v2&envId=linked-list
3移除链表中数组已存在的元素https://leetcode.cn/problems/delete-nodes-from-linked-list-present-in-array/?envType=problem-list-v2&envId=linked-list
4删除和为0的连续节点https://leetcode.cn/problems/remove-zero-sum-consecutive-nodes-from-linked-list/description/?envType=problem-list-v2&envId=linked-list

1.2.1删除已知的node节点【交换val值】

void deleteNode(ListNode* node) {//将node和后面的节点换个位置,然后删除int val=node->val;//暂存节点信息node->val=node->next->val;node->next->val=val;//删除node->next即可node->next=node->next->next;
}

1.2.2移除数组中已存在的节点【unordered_set】

ListNode* modifiedList(vector<int>& nums, ListNode* head) {ListNode* dummy=new ListNode(-1,head);unordered_set<int> s(nums.begin(),nums.end());ListNode* pre=dummy;ListNode* cur=dummy->next;while(cur!=nullptr){if(s.count(cur->val)){pre->next=cur->next;cur = pre->next;}else{cur=cur->next;pre=pre->next;}}return dummy->next;
}

1.2.3删除和为0的节点【前缀和】

前缀和的原理:
在这里插入图片描述
反复删去链表中由 总和值为0连续节点组成的序列,直到不存在这样的序列为止。
在这里插入图片描述

ListNode* removeZeroSumSublists(ListNode* head) {ListNode* dummy=new ListNode(0,head);//哈希表存储前缀和,以及最后出现的节点unordered_map<int,ListNode*> mp;int prefixsum=0;ListNode* p=dummy;while(p!=nullptr){prefixsum += p->val;mp[prefixsum]=p;// 相同前缀和会覆盖,保留最后一个p=p->next;}//第二次遍历prefixsum=0;p=dummy;while(p!=nullptr){prefixsum+=p->val;p->next=mp[prefixsum]->next;p=p->next;}return dummy->next;
}

1.3改(交换节点)

序号题目链接
1链表中的下一个最大节点https://leetcode.cn/problems/next-greater-node-in-linked-list/description/?envType=problem-list-v2&envId=linked-list
2删除右侧有一个更大数值的节点https://leetcode.cn/problems/remove-nodes-from-linked-list/?envType=problem-list-v2&envId=linked-list
3交换K和倒数第K个节点https://leetcode.cn/problems/swapping-nodes-in-a-linked-list/description/?envType=problem-list-v2&envId=linked-list
4合并0之间的节点https://leetcode.cn/problems/merge-nodes-in-between-zeros/description/?envType=problem-list-v2&envId=linked-list

1.3.1链表中的下一个最大节点

遍历整个链表,找到第一个比当前值大的元素。没有则为0。

解法1:

  • p指向当前节点
  • q指向当前节点的下一个节点。q向后移动直到找到第一个比p值大的节点,添加到数组中。
vector<int> nextLargerNodes(ListNode* head) {vector<int> result;ListNode* p=head;while(p!=nullptr){ListNode* q=p->next;int maxval=0;while(q!=nullptr){if(q->val > p->val){maxval=q->val;break;//找到第一个最大的就退出}q=q->next;}result.push_back(maxval);p=p->next;}return result;
}

解法2:单调栈。
右侧更大可以使用单调栈。单调栈的关键是维持栈内元素的单调性。
栈中每个索引对应的 values 值从栈底到栈顶逐渐变小。在这里插入图片描述

vector<int> nextLargerNodes(ListNode* head) {//将链表转换为数组vector<int> values;ListNode* p=head;while(p!=nullptr){values.push_back(p->val);p=p->next;}//初始化结果数组int n=values.size();vector<int> result(n,0);//单调栈stack<int> st;for(int i=0;i<n;i++){//将要出栈的元素全部出完while(!st.empty() && values[i] > values[st.top()]){int idx=st.top();st.pop();result[idx]=values[i];}//栈空 || 当前值<栈顶值——入栈st.push(i);}return result;
}

1.3.2删除右侧有一个更大数值的节点

当前值与后面值比较:若存在一个值 > 当前值,将当前值删掉。
思路与上述的单调栈差不多。重点在于栈内存储的是节点,最后返回时候需要使用头插法进行连接。

ListNode* removeNodes(ListNode* head) {stack<ListNode*> st;ListNode* p=head;while(p!=nullptr){//单调栈while(!st.empty() && p->val > st.top()->val){st.pop();}st.push(p);p=p->next;}//单调栈的元素“底大顶小”,因此实际需要从头向下连接//重构链表ListNode* dummy=new ListNode();ListNode* q=dummy;while(!st.empty()){ListNode* node=st.top();st.pop();// 将当前节点插入到dummy和dummy->next之间node->next = dummy->next;dummy->next = node;}return dummy->next;
}

1.3.3交换K和倒数第K个节点

ListNode* swapNodes(ListNode* head, int k) {ListNode* dummy=new ListNode(0,head);//求链表的长度int length=0;ListNode* cur=head;while(cur!=nullptr){cur=cur->next;length++;}//找到第k个节点p,下标为k-1ListNode* p=dummy;for(int i=0;i<=k-1;i++){p=p->next;}//找到倒数第k个节点q,下标为length-kListNode* q=dummy;for(int i=0;i<=length-k;i++){q=q->next;}//交换swap(p->val,q->val);return head;
}

1.3.4合并0之间的节点

ListNode* mergeNodes(ListNode* head) {//新建一个链表ListNode* dummy=new ListNode(0);ListNode* cur=dummy;int sum=0;ListNode* p=head->next;while(p!=nullptr){if(p->val!=0){sum += p->val;}else{ListNode* newnode=new ListNode(sum);cur->next=newnode;cur=cur->next;sum=0;}p=p->next;}return dummy->next;;
}

1.4其他

序号题目链接
1链表组件https://leetcode.cn/problems/linked-list-components/description/?envType=problem-list-v2&envId=linked-list
2螺旋矩阵https://leetcode.cn/problems/spiral-matrix-iv/description/?envType=problem-list-v2&envId=linked-list
3临界值间的距离https://leetcode.cn/problems/find-the-minimum-and-maximum-number-of-nodes-between-critical-points/description/?envType=problem-list-v2&envId=linked-list

1.4.1链表组件

在这里插入图片描述

int numComponents(ListNode* head, vector<int>& nums) {// 将nums中的值存入哈希集合,便于快速查找unordered_set<int> numSet(nums.begin(), nums.end());int count=0;int flag=0;ListNode* p=head;while(p!=nullptr){//当前节点值在nums中if(numSet.count(p->val)){//之前没碰到过:新的组件if(!flag){count++;flag=1;}}//当前节点值不在nums中else{ flag=0;}p=p->next;}return count;
}

1.4.2螺旋矩阵

给你两个整数:m 和 n ,表示矩阵的维数。
另给你一个整数链表的头节点 head 。
请你生成一个大小为 m x n 的螺旋矩阵,矩阵包含链表中的所有整数。链表中的整数从矩阵 左上角 开始、顺时针 按 螺旋 顺序填充。如果还存在剩余的空格,则用 -1 填充。

模拟螺旋填充的过程:

  • 螺旋填充的路径是 “右→下→左→上” 的循环,每次完成一圈后缩小边界。
    • 从左到右填充上边界,完成后上边界下移
    • 从上到下填充右边界,完成后右边界左移
    • 从右到左填充下边界(如果还有空间),完成后下边界上移
    • 从下到上填充左边界(如果还有空间),完成后左边界右移
  • 用四个变量控制当前填充的边界:上边界 (top)、下边界 (bottom)、左边界 (left)、右边界 (right)
  • 从链表中依次取元素,按照螺旋路径填充,直到所有元素用完或矩阵填满
vector<vector<int>> spiralMatrix(int m, int n, ListNode* head) {// 初始化m×n矩阵,全部填充为-1vector<vector<int>> matrix(m, vector<int>(n, -1));//定义边界int top=0;int bottom=m-1;int left=0;int right=n-1;//ListNode* current=head;while(current!=nullptr && top <= bottom && left <= right){// 1. 从左到右填充上边界for (int col = left; col <= right && current != nullptr; col++) {matrix[top][col] = current->val;current = current->next;}top++; // 上边界下移,该排已填满// 2. 从上到下填充右边界for (int row = top; row <= bottom && current != nullptr; row++) {matrix[row][right] = current->val;current = current->next;}right--; // 右边界左移,该列已填满// 3. 从右到左填充下边界(需确保还有未填充的行)if (top <= bottom) {for (int col = right; col >= left && current != nullptr; col--) {matrix[bottom][col] = current->val;current = current->next;}bottom--; // 下边界上移,该排已填满}// 4. 从下到上填充左边界(需确保还有未填充的列)if (left <= right) {for (int row = bottom; row >= top && current != nullptr; row--) {matrix[row][left] = current->val;current = current->next;}left++; // 左边界右移,该列已填满}}return matrix;
}

1.4.3临界值的距离

模拟即可:

  • 使用三个指针prev、curr和next分别指向当前节点的前一个节点、当前节点和后一个节点。
  • 对于每个节点,检查它是否是局部极大值点(大于前后节点)或局部极小值点(小于前后节点)。
  • 记录所有临界点的位置索引(从 1 开始计数)。
  • 计算出最小距离和最大距离。
vector<int> nodesBetweenCriticalPoints(ListNode* head) {if(head==nullptr || head->next==nullptr) return{-1,-1};vector<int> result;ListNode* pre=head;ListNode* cur=head->next;ListNode* next=cur->next;int pos=1;while(next!=nullptr){int ismax=(cur->val > pre->val) && (cur->val > next->val);int ismin=(cur->val < pre->val) && (cur->val < next->val);if(ismax || ismin) result.push_back(pos);//每一组极值pre=cur;cur=next;next=next->next;pos++;}if(result.size()<2) return {-1,-1};//计算最小距离(相邻临界点之间的最小距离)int mind=INT_MAX;for(int i=1;i<result.size();i++){mind=min(mind,result[i]-result[i-1]);}//最大距离(第一个和最后一个极值的距离)int maxd=result.back()-result.front();return {mind,maxd};
}

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

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

相关文章

【Android】OkHttp发起GET请求 POST请求

三三要成为安卓糕手 一&#xff1a;OkHttp介绍 OkHttp 是一个开源的、强大且高效的 HTTP 客户端库&#xff0c;主要用于在 Java后端和Android 项目中进行网络请求。 //在gradle中添加依赖 com.squareup.okhttp3:okhttp:4.12.0二&#xff1a;GET请求/*** 使用OkHttp发起get请求*…

[Mysql数据库] 知识点总结8

1. 请详细描述在复制拓扑中参与复制的线程类型以及各自所承担的功能。答&#xff1a;当从属服务器连接到主服务器时&#xff0c;在主服务器上会创建 Binlog 转储线程&#xff0c;在从属服务器上会默 认创建 I/O 线程和 SQL 线程。- Binlog 转储线程用于从二进制日志读取事件并将…

250829-Gitlab数据备份与恢复

下面给你一份可落地的迁移方案&#xff0c;保证 GitLab 的数据和配置完整迁移到服务器 B。你当前用的是 GitLab Omnibus&#xff08;docker 版&#xff09;&#xff0c;数据都在你映射的 3 个目录里&#xff08;/etc/gitlab, /var/log/gitlab, /var/opt/gitlab&#xff09;&…

吴恩达机器学习作业十一:异常检测

数据集在作业一异常检测异常检测就是发现与大部分对象不同的对象&#xff0c;其实就是发现离群点。异常检测有时也称偏差检测。异常对象是相对罕见的。用数据集建立概率模型p ( x )&#xff0c;如果新的测试数据在这个模型上小于某个阈值&#xff0c;则说它极大可能为异常点算法…

2000w 的数据量,mysql要进行几次IO操作,为什么

在 MySQL 中&#xff0c;2000 万数据量的表在进行查询时所需的 ​​IO 操作次数​​主要取决于 ​​索引结构&#xff08;B树层级&#xff09;​​、​​查询类型​​和 ​​数据分布特征​​。以下是具体分析&#xff1a;一、B树层级与 IO 次数的关系InnoDB 引擎通过 B树索引管…

【代码随想录day 22】 力扣 39. 组合总和

视频讲解&#xff1a;https://www.bilibili.com/video/BV1KT4y1M7HJ/?vd_sourcea935eaede74a204ec74fd041b917810c 文档讲解&#xff1a;https://programmercarl.com/0039.%E7%BB%84%E5%90%88%E6%80%BB%E5%92%8C.html#%E6%80%9D%E8%B7%AF 力扣题目&#xff1a;https://leetcod…

DrissionPage 实战:动态 IP 代理与百度翻译 API 数据抓取

本文将详细介绍如何使用 DrissionPage 实现动态 IP 代理访问&#xff0c;并结合百度翻译 API 进行数据抓取与处理。一、技术选型与架构设计1.1 为什么选择 DrissionPage&#xff1f;DrissionPage 作为新一代网络自动化工具&#xff0c;相比传统 Selenium Requests 方案具有显著…

策略模式:灵活应对算法动态切换

引言 在软件开发中&#xff0c;我们常常会遇到需要在运行时动态选择和切换算法或行为的场景。例如&#xff0c;电商系统中的多种支付方式、游戏中的不同难度设置&#xff0c;或是计算器中的各种运算符。传统的方法可能会使用复杂的条件判断语句&#xff08;如if-else或switch-c…

【C++ 】string类:深拷贝与浅拷贝解析

【C 】string类操作全解析-CSDN博客 1.stirng类的模拟实现 1.1 经典的string类问题 上面已经对string类进行了简单的介绍&#xff0c;大家只要能够正常使用即可。在面试中&#xff0c;面试官总喜欢要求自己来模拟实现string类&#xff0c;最主要是实现string类的构造、拷贝…

Decoder 解码器

Decoder 解码器&#xff1a; #include <stdio.h> #include <stdlib.h> #include <string.h>#include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <libswscale/swscale.h>#define WORD uint16_t #define DWORD ui…

globals() 小技巧

scheduler_class globals()[scheduler_class_name] Python 中一种 动态获取类对象 的常用技巧&#xff0c;属于 反射&#xff08;reflection&#xff09; 编程的范畴globals()Python 内置函数&#xff0c;返回一个 字典&#xff08;dict&#xff09;&#xff0c;包含当前模块&…

Android Studio 9.png制作

一、新建 二、把要做的图png导入进去 png图片建议 根据内容预留1像素可拉伸区域 eg:纯色或可渐变底色 三、右边创建.9.png 四、双击打开 1、绘制黑边 参考视频 2、缩放到800% ,移至右下 3、在下面和右边绘制整根黑线 4、根据png 位置左侧和上侧黑线 4.1 分析 红色方框为…

【百度】C++开发(25届提前批 一面)面经

文章目录1. 代码实现&#xff1a;说说LRU&#xff0c;并代码实现LRU为什么使用哈希表&#xff1f;&#xff08;有两个原因&#xff09;1. 仅用双向链表的缺陷2. 引入哈希表的作用1. 快速查找&#xff1a;2. 快速插入与删除&#xff1a;双向链表 哈希表的协作过程举例说明代码实…

Word文档怎么打印?Word打印技巧?【图文详解】单面/双面/指定页面/逆序等Word打印选项

一、问题背景 在日常办公、学习场景中&#xff0c;Word文档作为常用的文字处理载体&#xff0c;经常需要将电子内容转化为纸质版本&#xff0c;比如提交报告、打印学习资料、整理文档存档等。 但不少用户在尝试打印Word文档时&#xff0c;常会遇到各种阻碍&#xff1a;有的不清…

漫谈《数字图像处理》之基函数与基图像

在数字图像处理领域&#xff0c;基函数与基图像是贯穿理论分析与实际应用的核心概念 —— 它们如同 “乐高积木”&#xff0c;将复杂的图像信号拆解为可解释、可操作的基本单元&#xff0c;支撑起压缩、去噪、特征提取等一系列关键任务。从传统的傅里叶变换到前沿的因子场理论&…

打开多个Excel文件后快速关闭所有的文档,并且退出Excel应用

打开多个Excel文件后如果要快速关闭所有的文档&#xff0c;并且退出Excel应用&#xff0c;可以按住Shift键右上角的号&#xff08;关闭按钮&#xff09;。Word和PowerPoint也是一样的操作。如果有文档修改后没有保存&#xff0c;会提示是否保存。作为补充&#xff0c;先来看看两…

基于 PyTorch 构建 Dataset 与 DataLoader:从 TXT 文件读取到新增类别全流程指南

基于 PyTorch 构建 Dataset 与 DataLoader&#xff1a;从 TXT 文件读取到新增类别全流程指南在深度学习计算机视觉任务中&#xff0c;数据加载与预处理是模型训练的基础环节&#xff0c;直接影响模型的训练效率与最终性能。PyTorch 作为主流深度学习框架&#xff0c;提供了Data…

hive on tez如果是2个大表union会写几次临时文件到hdfs目录,数据量如何计算

如果是2个大表union会写几次临时文件到hdfs目录&#xff0c;数据量如何计算 在Hive on Tez中&#xff0c;两个大表执行UNION操作时&#xff0c;临时文件的写入次数和数据量&#xff0c;取决于UNION的类型&#xff08;UNION ALL还是UNION去重&#xff09;以及执行计划的Stage划分…

Web+js转uni-app+ts

一、入手uni-app 官方文档&#xff1a;uni-app官网 1.创建uni-app项目 1.1通过HBuilderX进行创建 官方地址&#xff1a;HBuilderX-高效极客技巧 1.2通过命令行创建 // js 版本的 npx degit dcloudio/uni-preset-vue#vite 项目名 npx degit dcloudio/uni-preset-vue#vite-…

IO_hw_8.29

1.使用fgets和fputs完成两个文件的拷贝&#xff0c;要求文件名使用外部传承2.注册登录代码3.思维导图4.牛客网刷题记录