随想录Day3|203. 移除链表元素、707. 设计链表、206. 反转链表
随想录Day3|203. 移除链表元素、707. 设计链表、206. 反转链表
之后的文章就不放题目链接了,因为真的很推荐Vscode的LeetCode插件,搜一下题号就可以开始code了!
我没怎么用过C++所以也是才开始熟悉它的特性,因为是链表的开始,所以搬运一下卡尔的这一小段代码。
// 单链表
struct ListNode {
int val; // 节点上存储的元素
ListNode *next; // 指向下一个节点的指针
ListNode(int x) : val(x), next(NULL) {} // 节点的构造函数
};
ListNode* head = new ListNode(5);
自己定义了构造函数就可以直接传入要赋的值使用,比C++默认生成的构造函数方便一些。
203. 移除链表元素
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回新的头节点 。
- 列表中的节点数目在范围
[0, 104]
内 1 <= Node.val <= 50
0 <= val <= 50
第一想法
需要特殊考虑如果要删除头节点。最坏的情况就是如果val
是1,这个链表前面一串都是1,则记录头节点变化会很繁琐,删除头节点重穿链表也会很繁琐。
所以采用dummy_head
作为不变的头节点,紧接着它之后的才是真·头节点。这里的dummy_head
就是纯粹只起到一个结构的作用,后面的都是有记录值的节点。
用时12min~
ListNode *removeElements(ListNode *head, int val)
{
ListNode *dummy_head = new ListNode(0, head);
ListNode *pre = dummy_head;
ListNode *cur = head;
while (cur)
{
if (cur->val == val)
{
ListNode *tmp = cur;
pre->next = cur->next; // 重新连接链表
cur = cur->next;
delete tmp; // 删除该节点
}
else
{
pre = cur;
cur = cur->next;
}
}
head = dummy_head->next;
delete dummy_head;
return head;
}
707. 设计链表
题目略长,总之就是写函数实现需要初始化、读取值、插入、头插、尾插、特定index插、删除,这些基本操作。
第一想法
要注意判断给定的index是否有效,那最好在初始化对象的时候就添加一个链表长度的属性,比较方便。以及最开头写的这一小段就可以用上了!
因为不太熟悉C++面向对象的语法,看卡尔的题解稍微纠结久了点,这个private定义数据类型的写法是第一次见哎。
用时32min~
class MyLinkedList
{
public:
struct ListNode
{
int val;
ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};
MyLinkedList() // 没看到数据类型对吧,别急
{
_dummyHead = new ListNode(0);
_size = 0;
}
int get(int index)
{
if (index >= _size || index < 0)
return -1;
ListNode *cur = _dummyHead->next;
while (index--)
cur = cur->next;
return cur->val;
}
void addAtHead(int val)
{
ListNode *node = new ListNode(val);
node->next = _dummyHead->next;
_dummyHead->next = node;
_size++;
}
void addAtTail(int val)
{
ListNode *node = new ListNode(val);
ListNode *cur = _dummyHead;
while (cur->next)
cur = cur->next;
cur->next = node;
_size++;
}
void addAtIndex(int index, int val)
{
if (index > _size)
return;
if (index < 0)
index = 0;
ListNode *node = new ListNode(val);
ListNode *cur = _dummyHead;
while (index--)
cur = cur->next;
node->next = cur->next;
cur->next = node;
_size++;
}
void deleteAtIndex(int index)
{
if (index >= _size || index < 0)
return;
ListNode *cur = _dummyHead;
while (index--)
cur = cur->next;
ListNode *tmp = cur->next;
cur->next = tmp->next;
delete tmp;
tmp = nullptr;
_size--;
}
private: // 没错数据类型是在这儿定义的!
int _size;
ListNode *_dummyHead;
};
在private部分才写数据类型是为了封装,只有在类中才能访问_dummyHead
和_size
。
206. 反转链表
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
- 链表中节点的数目范围是
[0, 5000]
-5000 <= Node.val <= 5000
第一想法
用一个pre
指针,一个cur
指针,每次cur->next
指向pre
就实现了反转。要尤其注意在要改变一个指针之前把它的原值保存下来(如果还要用),也要注意操作的顺序,比如需要首先pre = cur
再去改变cur
的值,也就是cur = tmp
,这里tmp
记录的是原来的链表中cur
的下一个。
看完随想录题解的想法
啊啊啊我第一次遇到这么长的报错,忘保存了总之巨大一串,然后才发现只有前两行有问题,我分别赋值为head
和head->next
了,这显然不对,因为pre
的初值就是反转后链表的最末端,一定要以nullptr
结尾。所以应该分别是nullptr
和head
。
用时13min~
ListNode *reverseList(ListNode *head)
{
ListNode *pre = nullptr;
ListNode *cur = head;
ListNode *tmp;
while (cur)
{
tmp = cur->next;
cur->next = pre;
pre = cur;
cur = tmp;
}
// 最后cur是nullptr,pre是新的头节点
return pre;
}
碎碎念
为什么每天都是凌晨写完啊hhh明天一定要优化一下时间段!不过还好这次是链表的初级,用时不太久。
真好,一般在十点半如果没有一个硬性约束我一定不会愿意开始一个新的工作项,不过这可是要打卡的!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了