【数据结构】猛猛干7道链表OJ
前言知识点
链表的调试技巧
int main()
{struct ListNode* n1=(struct ListNode*)malloc(sizeof(struct ListNode));assert(n1);struct ListNode* n2=(struct ListNode*)malloc(sizeof(struct ListNode));assert(n2);struct ListNode* n3=(struct ListNode*)malloc(sizeof(struct ListNode));assert(n3);struct ListNode* n4=(struct ListNode*)malloc(sizeof(struct ListNode));assert(n4);struct ListNode* n5=(struct ListNode*)malloc(sizeof(struct ListNode));assert(n5);n1->next=n2;n2->next=n3;n3->next=n4;n4->next=n5;n5->next=NULL;n1->val=1;n2->val=2;n3->val=3;n4->val=2;n5->val=1;while(newhead!=NULL){cout << newhead->val << "->" ;newhead=newhead->next;}cout << "NULL" << endl;return 0;
}
手搓一个链表出来,方便观察我们的调试与结果
一、移除链表元素(俩个方法)
1.1题目链接
203. 移除链表元素 - 力扣(LeetCode)
1.2题目描述
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点。
1.3解题思路
思路1
遍历链表,比对每一个节点的数据与val是否相等,如果相等,就free掉该节点。
时间复杂度:O(N) ;空间复杂度:O(1)
易错点(1.如果head->val就是val,那么head得更新 2.小心free的时候找不到next)
1、当链表的头结点的数据等于val时,我们free掉该节点后需要挪动head指针,让其指向新的头结点;
2、我们在遍历链表的时候需要记录前一个节点的地址,因为当我们free掉当前节点之后,我们要让前一个节点的next;链接到当前节点的下一个节点;
struct ListNode* removeElements(struct ListNode* head, int val) {struct ListNode* cur =head;struct ListNode* prev=NULL;//不用担心prev的节点更新问题while(cur){if(cur->val==val){if(cur==head)//头就得动手术,更新头节点{head=cur->next;free(cur);cur=head;}else{prev->next=cur->next;//意志遗传 prev越过6指向3free(cur);cur=prev->next;//cur到了3这个位置,还是比prev快一步}}else{prev=cur;//保证当没有节点删除的时候,起码prev在cur上cur=cur->next;//先把prev带到这里,然后自己又偷偷走一步,保证相对位置}}return head;
}
思路2
遍历链表,将不等于val的节点尾插到一个新的链表,将等于val的节点free掉。
时间复杂度:O(N) 空间复杂度:O(1)
难就难在我想不到用尾插,而是一位的改变指针指向,这令我非常晕乎乎
易错点
1、由于我们是把原链表中的节点尾插到新链表中去,所以我们插入元素的时候需要判断链表是否为空,如果为空,我们需要改变新链表的头结点;(这样的尾插并不方便)
2、当然,我们也可以把我们的新链表设计为带哨兵位的,这样我们直接进行尾插就行,但是要注意我们返回的应该是guard->next,因为哨兵位头结点不用于存储数据,同时在return之前记得把哨兵位头结点释放掉;
但要小心: newhead->next不要随便给别人赋值,这是一个随机值!!!(等到下面的反转链表就可以看到异常了)
3、由于原链表中最后一个节点的数据可能等于val,所以我们需要将新链表中尾结点的next置为NULL,防止通过它来访问已经被释放掉的节点。(这样的藕断丝连是会出问题的)
从代码逻辑中看出:最后一个是6的时候,cur=cur->next,也即是说把6直接给忽略掉了,并没有有效的删除,但是5->next还是指着6节点位置
struct ListNode* removeElements(struct ListNode* head, int val) {if(head==NULL){return NULL;}struct ListNode* cur =head;struct ListNode* prev=NULL;//不用担心prev的节点更新问题//因为要尾插,不想用tail了,定义一个Guardstruct ListNode* newhead=(struct ListNode*)malloc(sizeof(struct ListNode));struct ListNode* tail=newhead;while(cur){if(cur->val!=val){tail->next=cur;//更新尾节点链接//newhead->next=cur; 头节点别动!!!因为这个题不像反转链表,反转链表的newhead往前更新,因为箭头的指向在改变,所以头的改变到时候到了末尾正好是正确的tail=cur;//更新尾节点位置cur=cur->next;}else{cur=cur->next;// struct ListNode* next = cur->next;// free(cur);// cur = next;//杭哥这样删除是为了防止内存泄漏,但我直接往下一步走了}}tail->next=NULL;//这句是一个大bughead=newhead->next;free(newhead);return head;
}
(我这里cur节点偷了点懒,没有真正的free节点,这样会造成内存泄漏,虽然AC了,但是会有大问题,所以还是得多加小心!)
二、反转链表(俩个方法)
2.1题目链接
206. 反转链表 - 力扣(LeetCode)
2.2题目描述
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
2.3思路分析
思路1(利用迭代的思路)
指针的定义刚开始就是很有讲究的:
所以我们将n3定义在循环中,这也是我们常用的套路
n2负责改变指针指向,n3负责前进并且记录位置防止丢失,n1是用来告知n2指向哪里
struct ListNode* reverseList(struct ListNode* head) {struct ListNode* n1=NULL;struct ListNode* n2=head;while(n2){struct ListNode* n3=n2->next;n2->next=n1;n1=n2;n2=n3;}return n1;
}
思路2
将原链表中的节点头插到新链表中,然后返回新链表的头。(因为一直头插就可以改变链表顺序)
时间复杂度:O(N) 空间复杂度:O(1)
但是头插也有易错点:
1.记得更新头
2.记得定义一个next,要不然cur回不到原来的位置
3.还要小心空指针解引用的问题
//法二:取出链表的每一个节点头插
struct ListNode* reverseList(struct ListNode* head){struct ListNode* newhead = NULL;struct ListNode* cur = head;while(cur){struct ListNode* next = cur->next;cur->next = newhead;newhead = cur;cur = next;}return newhead;
}
三、 链表的中间节点(如果只让遍历一次,怎么办?)
3.1题目链接
876. 链表的中间结点 - 力扣(LeetCode)
3.2题目描述
给定一个头结点为 head
的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。时间复杂度:O(N) 空间复杂度:O(1)
3.3思路分析
思路1
遍历两遍数组,第一遍求出链表长度,第二步找出链表的中间节点并返回。
代码实现
//法一:遍历两次链表,第一次找出链表有几个节点,第二次返回链表的中间节点
struct ListNode* middleNode(struct ListNode* head){struct ListNode* cur = head;int count = 0;while(cur){count++;cur = cur->next;}cur = head;count /= 2;while(count--){cur = cur->next;}return cur;
}
思路2
由于这道题用第一种方法实现十分简单,所以在面试中面试官会加一个限制条件:要求只能遍历一遍链表;这时候就只能用快慢指针来解题了;
快慢指针:定义两个指针 – fast slow,慢指针一次走一步,快指针一次走两步;当链表长度为奇数,fast->next == NULL时,slow 为中间节点;当链表长度为偶数,fast == NULL 时,slow 为中间节点。时间复杂度:O(N) 空间复杂度:O(1)
快慢指针对于寻找节点是一把好手,我们一定要合理运用这种思维逻辑!
但是我们也还是得画出奇数偶数的情况
可以看出,对于奇数和偶数我们的fast指针一个在末尾,一个在NULL,所以只要我们while(fast && fast->next==NULL) 这样控制一下就可以兼容俩种情况啦~ 一定要多画图!!
易错点
我们在写while循环的条件时,必须写成 fast && fast->next,不能写成 fast->next && fast,因为当链表长度为偶数时,后面这种写法会发生空指针的解引用。
而且还有我们的while循环内部的逻辑是 && 我刚开始理解的是 || 但这样是不对的
//法二:使用快慢指针,slow一次走一步,fast一次走两步,只遍历一遍数组
//奇数个节点时,当fast->next == NULL时,slow刚好到达中间节点
//偶数个节点时,当fast == NULL时,slow刚好达到中间节点
struct ListNode* middleNode(struct ListNode* head){struct ListNode* fast, *slow;slow = fast = head;//注意:while条件中fast一定要写前面,不然偶数个时fast->next会造成空指针解引用while(fast && fast->next) //节点是奇数还是偶数未知注意:{slow = slow->next;fast = fast->next->next;}return slow;
}
四、链表中倒数第K个节点
4.1题目链接
链表中倒数第k个结点LEETCODE
4.2题目描述
输入一个链表,输出该链表中倒数第k个结点。
4.3思路分析
看到求节点问题,脑子里立马想到快慢指针法
但很明显的是,对于链表而言,往回找是非常困难的,所以就让fast走的时候,让slow也走,保持二者的相对距离
int kthToLast(struct ListNode* head, int k){struct ListNode* slow=head;struct ListNode* fast=head;if(head->next==NULL){return head->val;}while(k--){fast=fast->next;}while(fast){slow=slow->next;fast=fast->next;//这里会出现空指针的解引用!!!}return slow->val;
}
这个题难就难在最后的特殊情况得特判一下,因为fast=fast->next,当只有一个节点的时候,会出现空指针的解引用
4.4心得
五、合并两个有序链表
5.1题目链接
21. 合并两个有序链表 - 力扣(LeetCode)
5.2题目描述
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
5.3思路分析
大思路:创建新节点,不断更新tail->next取最小值进行尾插,当没有的时候,tail->next的next可以直接将整个链表接手
在数组中有一个类似的题目:88. 合并两个有序数组 - 力扣(LeetCode)(顺序表博客有讲,用三个指针,从后往前比较)
时间复杂度:O(N) 空间复杂度:O(1)
易错点
1、由于我们是把原链表中的节点尾插到新链表中去,所以我们插入元素的时候需要判断链表是否为空,如果为空,我们需要改变新链表的头结点;
2、当然,我们也可以把我们的新链表设计为带哨兵位头的,这样我们直接进行尾插就行,但是要注意我们返回的应该是guard->next,因为哨兵位头结点不用于存储数据,同时在return之前我们要记得把哨兵位头结点释放掉;
3、我以为尾插的时候加上guard头节点就不需要定义tail指针了,其实是我对结构的熟悉程度不够,我们的tail是必须得定义好的!!!!
4、插入的时候,我发现如果我把第一个链表的遍历拿下来赋值的话,它很容易就找不到下一个位置了,所以俩个while循环中都必须有next指针变量
等等等等
注意:循环体内的next指针可以不用定义!
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {//取小的尾插struct ListNode* guard=(struct ListNode*)malloc(sizeof(struct ListNode));struct ListNode* l1=list1,*l2=list2;//guard->next=NULL;struct ListNode* tail=guard;while(l1 && l2){if(l1->val <= l2->val){struct ListNode* next=l1->next;//方便l1可以回去原来的链表继续遍历tail->next=l1;//不断更新,只要最小的tail=l1;//tail向前移动一下l1=next;//l1继续回去遍历原先的链表}else{struct ListNode* next=l2->next;//方便l2可以回去原来的链表继续遍历tail->next=l2;//不断更新,只要最小的tail=l2;//tail向前移动一下l2=next;//l2继续回去遍历原先的链表}}if(l1==NULL){tail->next=l2;}else{tail->next=l1;}//最后将guard释放,更规范struct ListNode* head = guard->next;free(guard);guard = NULL;return head;
}
六、分割链表(特殊情况多)
6.1题目链接
86. 分隔链表 - 力扣(LeetCode)
6.2题目描述
分隔链表分为初阶版和进阶版,初阶版不要求我们保留每个分区中各节点的初始相对位置,而进阶版则要求要求我们保留每个分区中各节点的初始相对位置,这里我们讲解进阶版。
6.3思路分析
大思路是由于尾插不改变相对顺序,所以我们分别进行俩次尾插,再链接起来
eg:4 2 1 6 8 0 7这组数据,x==5 来进行分割
那么分割完毕后的样子是:4 2 1 0 6 8 7 我们画图进行演示
最后将这二者连接起来就大功告成
易错点
先说情况一和情况二:
感觉其实也大同小异,还是不往这方面想了,反正就是如果需要尾插,为了避免许多边界条件的处理,使链表的操作更加简洁和清晰,我们就创建头节点
通过下面的代码易错可以得知:如果不写头,还是很麻烦的,因为带头很容易控制随机值
情况四:
我们的lesstail已经指向了新节点,但是我们的2虽然乖乖的跟在了小节点元素队伍中去,但是我们的7节点与它仍有藕断丝连,所以我们必须断掉(但是合并俩个链表不一样,我们并不担心他们的藕断丝连,因为我们在while循环中一直更新tail的next指针节点)
这个易错点有点像移除链表元素的思路2时候那个一样,小伙伴们可以翻上去看看
代码易错点补充:
//LessGuard->next=NULL;
GreaterGuard->next = NULL;
//这俩个赋予空值看起来没有意义,但其实用处很大,因为我们下面有一个赋值操作
因为我们的节点是malloc出来的,也就说明里面都是随机值
LessTail->next=GreaterGuard->next;//将俩个链表连接起来
如果都是比 x 小的元素,那么GreaterGuard内部 else 就无法进去 ,cur 就无法给其赋值,那么如果不初始化的话就是随机值,这会引发巨大的错误!!!
(=左值不初始化不会报错,但是右值没有初始化会报一个非常大的错误,直接无法通过)
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
struct ListNode* partition(struct ListNode* head, int x) {struct ListNode* LessGuard=(struct ListNode*)malloc(sizeof(struct ListNode));struct ListNode* GreaterGuard=(struct ListNode*)malloc(sizeof(struct ListNode));struct ListNode* cur=head,*LessTail=LessGuard,*GreaterTail=GreaterGuard;//LessGuard->next=NULL;GreaterGuard->next = NULL;//这俩个赋予空值看起来没有意义,但其实用处很大,因为我们下面有一个赋值操作if(head==NULL){return NULL;}if(head->next==NULL){return head;}while(cur){//struct ListNode* next=cur->next;//因为我们这个题并没有修改cur的值,所以不需要next变量让我们回去if(cur->val < x){LessTail->next=cur;LessTail = cur;cur=cur->next;}else{GreaterTail->next=cur;GreaterTail=cur;cur=cur->next;}}LessTail->next=GreaterGuard->next;//将俩个链表连接起来GreaterTail->next=NULL;//避免藕断丝连//释放哨兵位头结点//head = LessGuard->next;// free(GreaterGuard);// free(LessGuard);// GreaterGuard = NULL;// LessGuard = NULL;return LessGuard->next;
}
七、回文链表(不可以开辟新空间)
7.1题目链接
234. 回文链表 - 力扣(LeetCode)
7.2题目描述
给定一个链表的 头节点 head ,请判断其是否为回文链表。如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。
7.3思路分析
大思路:
1.找到链表的中间节点,将链表中间及以后的节点反转(中间节点用快慢,反转用头插或者用迭代n1,n2,n3)
2.然后用两个指针,一个指向链表开头,另一个指向反转部分的开头
3.cur指向原先的链表,遍历观察二者的val是否相等。
时间复杂度:O(N) 空间复杂度:O(1)
易错点:
我们反转的是中间及以后的节点,但是并未改变中间节点的前一个节点的next;也就是说,中间节点的前一个节点指向的是反转后的链表的最后一个节点;所以不管是链表长度是奇数还是偶数,我们都可以直接判断指针指向节点的val是否相等。
但是在写代码的时候,这个奇偶性还是很磨人的
但是很难受的是,直接写出数字并不可以很好的反映出链表内部的结构,以及那些元素连接在了一起,所以我们先来分析一下1 2 3 2 1反转之后的链表情况
这个时候再来分析cur和 rmid 的关系就很好理解了
很幸运的是,奇数这里有一个自己比较自己的一个效果(我刚开始没有分析出来head的链表元素为1 2 3 把我痛苦了好久)
奇数解决了,那么偶数就更简单啦!只需要一个一个往后走,一旦遇到不合适的咔嚓结束就好啦
最后放一个情况总结图:
希望看到这里大家可以明白我们的循环条件如何把控(快吐血的我...)
反正想要强调的就一件事:中间节点后面的链表反转完之后,我们的中间节点的前一个位置与原先后面的节点仍然有关系!
完整代码:
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
struct ListNode* middleNode(struct ListNode* head) {struct ListNode* slow=head;struct ListNode* fast=head;while(fast && fast->next){slow=slow->next;//slow走一步fast=fast->next->next;//fast走俩步}return slow;
}
struct ListNode* reverseList(struct ListNode* head)
{struct ListNode* n1=NULL;struct ListNode* n2=head;while(n2){struct ListNode* n3=n2->next;n2->next=n1;//迭代n1=n2;n2=n3;}return n1;
}
bool isPalindrome(struct ListNode* head)
{struct ListNode* rmid=(reverseList(middleNode(head)));//先找到链表的中间节点,再反转他struct ListNode* cur=head;while(cur && rmid)//开始遍历这俩个,都不可以为空,为空就结束{if(cur->val!=rmid->val){return false;}cur=cur->next;rmid=rmid->next;}return true;
}
总结:链表做题套路
删除元素得定义prev指针
这个知识点从第一道题目,删除链表元素获取而来
小心malloc的节点,->next的随机值问题,尤其是作为=右值的时候
这个知识点从反转链表的头插那里有点小涉及,但直接报错的是那个划分链表元素,俩次尾插最后连接起来的那个题目,因为那个题目有一个
LessTail->next=GreaterGuard->next;//将俩个链表连接起来
这里等号右值如果不置空的话,很容易出问题
头插的时候,由于头节点的更新,我们的cur往往会被覆盖,这个时候while内部创建next是很有必要的(典型代表:反转链表之头插法)
为了避免空指针被解引用的问题,我们一般在循环中创建next变量
看到求中间节点或者第几个节点或者倒数第几个节点就用快慢指针
对于需要对链表进行操作的,我们除了可以在原先链表中建立指针,我们还可以新开辟一个头节点,使得我们可以进行尾插和头插(尾插不改变元素顺序,头插改变元素顺序)
关于哨兵位带头的问题(要尾删,必建头)
我们必须认识到一个问题:单链表就适合头插头删,不适合尾插尾删
带头对于头插也有好处:这样可以避免重复的更新头节点,很方便嘞!(但是杭哥建议头插不带哨兵头也可以,但是得记得更新)
对于尾插的好处:省略特殊情况的判空
相关文章:

【数据结构】猛猛干7道链表OJ
前言知识点 链表的调试技巧 int main() {struct ListNode* n1(struct ListNode*)malloc(sizeof(struct ListNode));assert(n1);struct ListNode* n2(struct ListNode*)malloc(sizeof(struct ListNode));assert(n2);struct ListNode* n3(struct ListNode*)malloc(sizeof(struc…...

记录C++中,子类同名属性并不能完全覆盖父类属性的问题
问题代码: 首先看一段代码:很简单,就是BBB继承自AAA,然后BBB重写定义了同名属性,然后调用父类AAA的打印函数: #include <iostream> using namespace std;class AAA { public:AAA() {}~AAA() {}void …...

使用 ONLYOFFICE API 构建 Java 转换器,在 Word 和 PDF 之间进行转换
文章作者:ajun 随着文档处理需求的增加,格式转换成为了一个重要的需求点。由于PDF格式具有跨平台、不易被篡改的特性,将Word格式(.docx)转换为PDF格式(.pdf)的需求尤为强烈。ONLYOFFICE作为一个强大的办公套件,提供了这样的转换功…...

SpringCloudAlibaba Nacos配置及应用
Nacos搭建及配置 nacos本机服务搭建 windows上搭建单机nacos: Releases alibaba/nacos GitHub 下载安装包 下载本地,解压,直接运行(保证安装包的绝度路径只有英文字符,有中文会导致运行失败)ÿ…...

#Linux(权限管理)
(一)发行版:Ubuntu16.04.7 (二)记录: (1) (2)-开头代表普通文件 划分为三组: rw- rw- r-- rw-: 文件拥有…...

easyExcel复杂表头导出
代码 import com.alibaba.excel.EasyExcel; import com.alibaba.excel.write.style.column.AbstractColumnWidthStyleStrategy; import com.alibaba.excel.write.style.column.LongestMatchColumnWidthStyleStrategy;import java.util.ArrayList; import java.util.Arrays; imp…...

【大数据】五、yarn基础
Yarn Yarn 是用来做分布式系统中的资源协调技术 MapReduce 1.x 对于 MapReduce 1.x 的版本上: 由 Client 发起计算请求,Job Tracker 接收请求之后分发给各个TaskTrack进行执行 在这个阶段,资源的管理与请求的计算是集成在 mapreduce 上的…...

语义分割实战项目(从原理到代码环境配置)
语义分割(Semantic Segmentation) 先看结果: 是计算机视觉和深度学习领域的一项核心任务,它主要致力于对图像中的每一个像素进行分类,赋予每个像素一个类别标签,以达到理解图像内容的目的。换句话说&#…...

基于python+vue 的一加剧场管理系统的设计与实现flask-django-nodejs-php
二十一世纪我们的社会进入了信息时代,信息管理系统的建立,大大提高了人们信息化水平。传统的管理方式对时间、地点的限制太多,而在线管理系统刚好能满足这些需求,在线管理系统突破了传统管理方式的局限性。于是本文针对这一需求设…...

【Entity Framework】 EF中DbContext类详解
【Entity Framework】 EF中DbContext类详解 一、概述 DbContext类是实体框架的重要组成部分。它是应用域或实例类与数据库交互的桥梁。 从上图可以看出DbContext是负责与数据交互作为对象的主要类。DbContext负责以下活动: EntitySet:DbContext包含…...

智能风扇的新篇章:唯创知音WTK6900G语音识别芯片引领行业革新
随着科技浪潮的推进,智能化技术逐渐渗透到生活的每一个角落,家电领域尤为明显。风扇,这一夏日清凉神器,也通过智能化改造,焕发出前所未有的光彩。其中,智能语音控制功能的加入,为风扇的使用带来…...
[json.exception.type_error.316] invalid UTF-8 byte报错
[json.exception.type_error.316] invalid UTF-8 byte at index 1: 解决方法重新编译程序即可。...

深度强化学习(九)(改进策略梯度)
深度强化学习(九)(改进策略梯度) 一.带基线的策略梯度方法 Theorem: 设 b b b 是任意的函数, b b b与 A A A无关。把 b b b 作为动作价值函数 Q π ( S , A ) Q_\pi(S, A) Qπ(S,A) 的基线, 对策略梯度没有影响: ∇ θ J …...
Oracle修改Number类型精度报错:ORA-01440
修改Number类型的字段的精度SQL ALTER TABLE XXXX MODIFY RATE NUMBER(30,6); 如果表已经存在数据,报错信息如下: ORA-01440: column to be modified must be empty to decrease precision or scale 废话不多说,解决方案如下:…...
美团到店-后端开发一面
1. 介绍一下spring的两大核心思想 2. 介绍一下java的代理,以及动态代理和静态代理的区别 3. spring动态代理是如何生成的,jdk动态代理和cglib的区别 4. 介绍一下synchronized关键字、以及synchronized锁和lock的区别 5. 讲一下java中synchronized的锁升级…...
面试算法-77-括号生成
题目 数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。 示例 1: 输入:n 3 输出:[“((()))”,“(()())”,“(())()”,“()(())”,“()()()”] 解 class Solution {publ…...

webpack5零基础入门-12搭建开发服务器
1.目的 每次写完代码都需要手动输入指令才能编译代码,太麻烦了,我们希望一切自动化 2.安装相关包 npm install --save-dev webpack-dev-server 3.添加配置 在webpack.config.js中添加devServer相关配置 /**开发服务器 */devServer: {host: localhos…...

opengl日记10-opengl使用多个纹理示例
文章目录 环境代码CMakeLists.txt文件内容不变。fragmentShaderSource.fsvertexShaderSource.vsmain.cpp 总结 环境 系统:ubuntu20.04opengl版本:4.6glfw版本:3.3glad版本:4.6cmake版本:3.16.3gcc版本:10.…...

锂电池寿命预测 | Matlab基于ALO-SVR蚁狮优化支持向量回归的锂离子电池剩余寿命预测
目录 预测效果基本介绍程序设计参考资料 预测效果 基本介绍 锂电池寿命预测 | Matlab基于ALO-SVR蚁狮优化支持向量回归的锂离子电池剩余寿命预测 基于蚁狮优化和支持向量回归的锂离子电池剩余寿命预测: 1、提取NASA数据集的电池容量,以历史容量作为输入,…...
动态规划15 | ● 392.判断子序列 ● *115.不同的子序列
392.判断子序列 https://programmercarl.com/0392.%E5%88%A4%E6%96%AD%E5%AD%90%E5%BA%8F%E5%88%97.html 考点 子序列问题 我的思路 dp[i][j]的含义是,两个序列分别取到下标为i和j的时候,他们是否满足前者是后者的子序列,满足为True&#x…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...

python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
QMC5883L的驱动
简介 本篇文章的代码已经上传到了github上面,开源代码 作为一个电子罗盘模块,我们可以通过I2C从中获取偏航角yaw,相对于六轴陀螺仪的yaw,qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...

基于当前项目通过npm包形式暴露公共组件
1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...

NFT模式:数字资产确权与链游经济系统构建
NFT模式:数字资产确权与链游经济系统构建 ——从技术架构到可持续生态的范式革命 一、确权技术革新:构建可信数字资产基石 1. 区块链底层架构的进化 跨链互操作协议:基于LayerZero协议实现以太坊、Solana等公链资产互通,通过零知…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...