算法整理:链表

链表定义

struct ListNode { int val;ListNode *next;ListNode(int x) : val(x), next(nullptr) {}
};

链表的遍历ListNode p=head; while(p!=null) p=p.next; 

找到链表的尾结点p=head; while(p.next!=null)p=p.next;

链表节点的个数

          p=head; cnt=0; //cnt与p不同步对应

          while(p!=null):cnt++; p=p.next

          cnt与p不同步对应的原因:

          while停止后,p为null,cnt为对应到最后一个节点上面

         规律:开始的时候同步和结束时候的同步规律是一致的。

链表删除

 注意:1.删除节点需要dummyNode  2.最后返回的是dummyNode.next而不是head.

       因为head可能被删掉

 ListNode dummyNode=new ListNode();

   dummyNode.next=head;

   (p.next为待删除节点)

    p.next=p.next.next;

   return dummyNode.next;

ListNode* deleteNode(ListNode* head, ListNode* p) {// 创建一个虚拟头节点,便于处理链表头部的删除操作ListNode dummyNode(0);dummyNode.next = head;// 将虚拟头节点的下一个节点指向原链表头节点ListNode* prev = &dummyNode;// 遍历链表,找到待删除节点的前驱节点while (prev->next&& prev->next != p) {prev = prev->next;}// 如果待删除节点存在,则进行删除操作if (prev->next) {prev->next = prev->next->next;} else {std::cout << "Target node not found in the list." << std::endl;}// 返回处理后的新链表头节点(即原链表头节点)return dummyNode.next;
}

链表插入

  (1)头插法: dummyNode,p:

p.next=dummyNode.next;
dummyNode.next=p;

  (2)尾插法

tail,p:tail.next=p; tail=p;

   在尾插法的过程中,tail.next不需要清空:

   每次插入时tail.next都会重定向到待插入的节点

   最后tail.next=null

找到链表的第index个节点

int i=1;
p=head;
//计数变量和p索引始终同步对应:while停止后,i对应p.
while(i<index&&p!=null)p=p.next;i++;

链表翻转 dummyNode + 头插法

   ListNode dummyNode=new ListNode();dummyNode.next=null;ListNode p=head;if(head==null)return null;ListNode q=p.next;while(p!=null)q=p.next;p.next=dummyNode.next;dummyNode.next=p;p=q;return dummyNode.next;
两个链表第一个公共的节点

 (1)求两个链表长度n1,n2  

 (2)长的链表走|n1-n2|步,使两个链表长度相同

 (3)两个链表一起走,相等返回,走到头返回null

倒数第k个节点

(1) 求节点个数n

(2)求第n-k+1个节点

删除重复节点

 (1)增加虚拟头结点

   (2)链表节点的删除

     p.next=p.next.next

删除链表倒数第n个节点

   (1)添加虚拟头结点

   (2)求链表长度l

   (3)找第l-n的节点并删除

判断环

         如果有环:slow和fast走一定会相遇

         如果没有环:在有限次遍历链表后,一定为空

if head==null:return false//特判
slow=head;
fast=head.next;   
while(slow!=fast&&slow!=null&&slow.next!=null&&fast!=null&&fast.next!=null)slow=slow.next;fast=fast.next.next;if(slow==fast)return true;return false 
判断环的入口

(1)fast和slow置头结点,速度为2,1

(2)相遇后fast置头结点,速度为1

(3)fast和slow相遇的节点是入口

fast=pHead;
slow=pHead;
while(fast!=null&&fast.next!=null){fast=fast.next.next;slow=slow.next;if(fast==slow){fast=pHead;while(fast!=slow){fast=fast.next;slow=slow.next;}return fast;
return nullptr//如果遍历到空节点,说明没有环,返回null
合并两个排序的链表
p=head1,q=head2;
tail = dummyNode;
while(p!=null&&q!=null){if(p.val<q.val)tail.next=p;tail=p;p=p.next;else  tail.next=q;tail=q;q=q.next;
}tail直接指向非空的一个链表,如果两个链表都是空,那么就指向空
tail.next=(p==null)?q:p;
return dummyNode.next;
回文链表

存储链表的值

指定区间反转链表

思路:切断后反转局部链表后重接回去。node1,node2,..,p,start,...end,q...noden

需要找到p,q,start,end

 (1)把区间的链表单独拎出来:

 p.next=null; end.next=null;

 (2)反转区间reverse

 (3)重写接回去

  reverse(start);

增加虚拟头结点:

  如果说从第一个开始就翻转,那么就得分情况讨论,所以要添加一个虚拟头结点。

奇偶链表

给定单链表的头节点 head ,将所有索引为奇数的节点和索引为偶数的节点分别组合在一起,然后返回重新排序的列表。 O(1) 的额外空间复杂度和 O(n) 的时间复杂度

两个虚拟头结点,使用尾插法,然后合并到一起。

ListNode *odd = new ListNode(0);
ListNode *even = new ListNode(0);ListNode *tail1=odd;ListNode *tail2=even;ListNode *p = head;int idx=1;while(p!=nullptr){if(idx%2!=0){tail1->next=p;tail1=p;p=p->next;idx++;}else{tail2->next=p;tail2=p;p=p->next;idx++;}}
//最后需要把tail2->next置空tail2->next=nullptr;tail1->next=even->next;return odd->next;}

尾插法最后置空,否则会出现野指针错误。

LeetCode 25 k个一组翻转链表

使用栈,进栈k次,尾插法就是逆序的。

需要考虑剩下的链表个数够不够 k 个(因为不够 k 个不用翻转)。已经翻转的部分要与剩下链表连接起来。

stack<ListNode*>st
ListNode dummy(0)
ListNode* tail = &dummy
while (true):int count = 0;ListNode* p = head;/ 将k个节点压入栈中while (p&&count<k):st.push(p);p=p->next;count++;if(count != k)tail->next=headbreakwhile (!stack.empty())tail->next = stack.top()stack.pop()tail = tail->next   tail->next = phead = p
return dummy->next

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

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

相关文章

LocalDateTime 前后端传输问题

后端使用json形式接收前端传来的LocalDateTime&#xff0c;则添加下面的JsonFormat注释 同时后端返回给前端的json中带有LocalDateTime的话&#xff0c;也添加JsonFormat注解 JsonFormat(pattern "yyyy-MM-dd HH:mm:ss", timezone "GMT8") private Loca…

蓝桥杯真题:七段码

import java.util.Scanner; import java.util.ArrayList; // 1:无需package // 2: 类名必须Main, 不可修改public class Main {public static void main(String[] args){// 连接关系图int[][] map new int[][]{{0, 1, 0, 0, 0, 1, 0},{1, 0, 1, 0, 0, 0, 1},{0, 1, 0, 1, 0, 0…

通讯录项目实现

引言&#xff1a;通过顺序表的逻辑实现通讯录。这里就不讲关于顺序表的函数了。如果有不明白的可以看我写的顺序表的博客。 目录 顺序表与通讯录的比较 各源文件文件大榄 Contact.c中通讯录相关函数的定义 初始化和销毁通讯录 添加联系人&#xff1a; 删除联系人&#xf…

c++的学习之路:10、string(2)

本章主要说一下模拟实现string类的部分功能&#xff0c;文章末附上所有代码。 目录 一、构造函数与析构函数 二、拷贝构造 三、c_str 四、【】和迭代器的遍历与访问 五、size 六、判断 七、reserve 八、push_back 九、resize 十、append 十一、 十二、insert 十…

Spirngboot JWT快速配置和使用

2、JWT 2.1、JWT介绍 JWT是JSON Web Token的缩写&#xff0c;即JSON Web令牌&#xff0c;是一种自包含令牌。 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。 JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息&#xff0c;以便于从…

day25打卡:回溯算法part02

day25打卡&#xff1a;回溯算法part02 216.组合总和三 原题链接 代码随想录链接 和经典的回溯题目很相似&#xff0c;只是需要在每层for循环中都记录当前的总和&#xff1b; Java代码如下&#xff1a; class Solution {List<List<Integer>> result new Arra…

【DevOps工具篇】Keycloak中设置与OpenLDAP认证集成

【DevOps工具篇】Keycloak中设置与OpenLDAP认证集成 目录 【DevOps工具篇】Keycloak中设置与OpenLDAP认证集成步骤 1. 启动一个用于安装 OpenLDAP 的 EC2 实例步骤 2. 安装 OpenLDAP启动 docker 容器查看所有用户信息extended LDIFLDAPv3base <ou=users,dc=example,dc=org&g…

Redis的5大常见数据类型的用法

上一篇文章我们讲了Redis的10大应用场景&#xff0c;这一篇文章就针对Redis的常用数据结构进行一个说明&#xff0c;通过示例的形式演示每一种数据结构如何使用。 当涉及Redis的数据操作时&#xff0c;不同数据类型对应的不同数据结构&#xff0c;如下就对5大常用的数据类型进行…

Transformer,革命性的深度学习架构

Transformer 是一种革命性的深度学习架构&#xff0c;专门设计用于处理序列数据&#xff0c;特别是在自然语言处理&#xff08;NLP&#xff09;任务中表现卓越。它由 Vaswani 等人在 2017 年发表的论文《Attention is All You Need》中首次提出&#xff0c;打破了当时基于循环神…

2024最新版Android studio安装入门教程(非常详细)

目录 JDK安装与配置 一、下载JDK 二、JDK安装 三、JDK的环境配置 四、JDK的配置验证 Android studio安装 Android studio连接手机真机调试&#xff08;以华为鸿蒙为例&#xff09; 一、新建一个android项目 二、进入项目面板 三、配置Android Studio 四、安装手机驱…

【linux】进程替换的应用|shell解释器的实现

当我们学过了进程替换之后&#xff0c;本篇文章可以根据进程替换的知识带你自主实现一个shell命令行 实现步骤 1.显示命令行提示 2.读取输入指令以及对应选项 3.分割第二步的指令以及选项到命令行参数表中 4.处理内建命令 5.进程替换 1.显示命令行提示 我们通过观察bash的命令行…

03-Docker入门

03-Docker入门 在运行之前&#xff0c;首先通过如下命令确认Docker的状态 sudo docker info运行第一个容器 运行如下命令&#xff0c;运行我们的第一个centos容器&#xff0c;如果本地没有该镜像&#xff0c;就会自动下载。这里的两个参数&#xff0c;-i保证我们可以输入&am…

滑动窗口算法 - LCR 014. 字符串的排列

前言 接前文 滑动窗口算法 - LC76 最小覆盖子串-CSDN博客&#xff0c;此题也是套用滑窗模板&#xff0c;但是在两个细节点处稍有不同。 正文 LCR 014. 字符串的排列 给定两个字符串 s1 和 s2&#xff0c;写一个函数来判断 s2 是否包含 s1 的某个变位词。 换句话说&#xf…

Linux多进程通信总结——进程间通信看这一篇足够啦!

1.进程间通信方式综合比较 优点缺点有名管道1&#xff09;任意进程间通信1&#xff09;缓冲区有限无名管道1&#xff09;简单方便1&#xff09;单向通信2&#xff09;父子进程间通信3&#xff09;缓冲区有限消息队列1&#xff09;任意进程通信2&#xff09;无需考虑进程间同步…

Linux 文件相关命令

一、查看文件命令 1&#xff09;浏览文件less 默认查看文件的前 10 行。 less /etc/services ##功能说明&#xff1a; #1.默认打开首屏内容 #2.按【回车】按行访问 #3.按【空格】按屏访问 #4.【从上向下】搜索用/111,搜索包含111的内容&#xff0c;此时按n继续向下搜&#x…

PCL 基于直线进行KMeans聚类

文章目录 一、K-Means算法二、K-Means算法步骤三、实现代码四、实现效果参考文献一、K-Means算法 在诸多的聚类方法中,K-Means聚类方法是属于“基于原型的聚类”(也称为原型聚类)的方法,此类方法均是假设聚类结构能通过一组原型刻画,在现实聚类中极为常用。通常情况下,该类…

JAVAEE之IoCDI

Spring 是⼀个 IoC&#xff08;控制反转&#xff09;容器&#xff0c;作为容器, 那么它就具备两个最基础的功能&#xff1a; • 存 • 取 Spring 容器管理的主要是对象, 这些对象, 我们称之为"Bean". 我们把这些对象交由Spring管理, 由 Spring来负责对象的创建…

想学网络安全,从哪里开始?网络安全的学习路线

网络安全学习路线&#xff1a; 想学习网络安全专业的知识&#xff0c;想当黑客&#xff0c;但是不知道该从哪里开始学。 我给你一个路线&#xff01; 清晰图片和大纲&#xff1a;https://docs.qq.com/doc/DU1lpVFpSbWVrd2p3

面试官:为什么忘记密码要重置,而不是告诉我原密码?

前端训练营&#xff1a;1v1私教&#xff0c;终身辅导计划&#xff0c;帮你拿到满意的 offer。 已帮助数百位同学拿到了中大厂 offer。欢迎来撩~~~~~~~~ Hello&#xff0c;大家好&#xff0c;我是 Sunday。 最近有个同学在面试中遇到了一个很有意思的问题&#xff0c;我相信大多…

基于单片机的电动车电池充电保护装置设计

摘 要:针对电动车充电安全方面的隐患,提出基于单片机控制的电动车电池充电保护装置的设 计。该装置以单片机为核心,包含数字温度传感器、控制按钮、外接显示屏、降温风扇及其他组件。控制按钮主要用来设定温度,温度传感器分别装在蓄电池和充电器内部,若充电器或蓄电池温度…