本文是计划花一些时间学习《代码随想录》时做一个记录,水平有限,可能理解有误,内容摘抄总结自Carl大佬的,感谢大佬开源的面向算法初学者的好资料
链表理论基础
链表是一种结构体,通过上一个链表元素中的指针属性来指示上一个或者下一个链表元素,通过这种方式,链表可以在整体上呈现一些线性、环形、或者双向的结构。
保存链表时记录的是链表的头节点,即链表的入口,链表元素中必然至少含有一个指针属性,用于指示下一个链表元素的地址,因此,链表元素在内存中不是连续的。
链表不支持随机访问,但是支持O(1)的增删
- 链表相比数组的这个特性使得链表在增删上复杂度是O(1)的,只需要控制需要变动的变量周围前后元素的上一个/下一个地址记录即可。
- 但是相对的要具体访问第几个元素,就必须从头节点一个一个遍历,复杂度为O(n),在具体的题目中需要通过记录中间节点等方式对这个缺点做优化,不然配合情景轻松会出现O(n^2)的情况。
由此、链表相对与数组,适合更加需要增删、对查询需求低的情景
注意空间回收
这是对中间元素的逻辑上的删除,从此用这个链表没有办法访问到之前那个变量,但是其依然留在内存里,C++这类语言,应该由程序员手动进行回收,Java、Python等有自己回收机制的就不用了。
力扣真题
203.移除链表元素
link
基本删除,注意
- 原链表为空(判断一下就行)
- 原链表全部元素都需要移除(搜索两遍)
- 注意写出内存清除,虽然并不影响执行结果
707.设计链表
link
对链表常见的几个接口做一个实现
- 使用虚拟头节点,解决第一个点的删除、增加与后续节点不同的问题
- 维护一个链表大小,方便对链表进行判空等操作
206. 反转链表
要想在链表中不创建额外的n个空间实现原地修改,就只能修改每个节点的next指针,对于单向链表,问题就是在修改某个节点的next时,要记住其上一个节点和下一个节点,才能实现方便的修改。
三个指针记录上一个要指向的节点,这一个要改变next的节点,和下一个要改变的next原先指向的节点,只需要判断到要改变的这一个节点为nullptr时,就结束了,此时上一个循环中保存在上一个节点就是链表最后一个值。
主要还是,变换链表的次序,不需要真正改变其存储地址和存储,只需要改变链接的方式
24. 两两交换链表中的节点
计划直接弄两个指针换一下value就行,但是此题目说不能修改内部值,那我们只能改变想法,还是通过改变链接的方式进行交换。
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* vir = new ListNode();//虚拟头节点
vir->next = head;
ListNode* temp = vir;
while (temp->next!=nullptr&&temp->next->next!=nullptr){
//后两个有值————需要交换,整理好需要排成的顺序,1、2、3
ListNode* first = temp->next->next;
ListNode* second = temp->next;
ListNode* third = first->next;
temp->next = first;
first->next = second;
second->next = third;
//放在整理好的节点1、2末尾,指向下一个可能需要排的3
temp = second;
}
//后面不够两个值————不需要交换,输出头节点
return vir->next;
}
};
关于力扣
看了卡哥说这个,其实我还挺信这个击败的,我的代码一般比较啰嗦动不动申请个stl容器之类的,一般复杂度都会比一样的方法大一些,看了这个还挺开心的,leetcode真是这样吗,不过能过就很好了 :)