代码随想录算法训练营第三天| 203.移除链表元素 707.设计链表 206.反转链表
1.代码随想录算法训练营第二天| 977.有序数组的平方,209.长度最小的子数列,59.螺旋矩阵Ⅱ2.代码随想录算法训练营第一天| 704. 二分查找、27. 移除元素
3.代码随想录算法训练营第三天| 203.移除链表元素 707.设计链表 206.反转链表
4.代码随想录算法训练营第四天| 24. 两两交换链表中的节点, 19.删除链表的倒数第N个结点,面试题02.07.链表相交,142.环形链表Ⅱ5.代码随想录算法训练营第六天| 242.有效的字母异位词,349.两个数组的交集,202.快乐数,1.两数之和6.代码随想录算法训练营第7天| ● 454.四数相加II ● 383. 赎金信 ● 15. 三数之和 ● 18. 四数之和7.代码随想录算法训练营第8天| ● 344.反转字符串 ● 541. 反转字符串II ● 剑指Offer 05.替换空格 ● 151.翻转字符串里的单词 ● 剑指Offer58-II.左旋转字符串8.代码随想录算法训练营第9天| ●28. 实现 strStr() ●459.重复的子字符串 ●字符串总结 ●双指针回顾 9.代码随想录算法训练营第10天| 232.用栈实现队列 ● 225. 用队列实现栈10.代码随想录算法训练营day13| ● 239. 滑动窗口最大值 ● 347.前 K 个高频元素 ● 总结11.代码随想录算法训练营day11| ● 20. 有效的括号 ● 1047. 删除字符串中的所有相邻重复项 ● 150. 逆波兰表达式求值12.代码随想录算法训练营day14| ● 二叉树理论基础 ● 递归遍历 ● 迭代遍历 ● 统一迭代13.代码随想录算法训练营day15 | ● 层序遍历 10 ● 226.翻转二叉树 ● 101.对称二叉树 2 14.代码随想录算法训练营day16 | ● 104.二叉树的最大深度 559.n叉树的最大深度 ● 111.二叉树的最小深度 ● 222.完全二叉树的节点个数15.代码随想录算法训练营day17 | ● 110.平衡二叉树 ● 257. 二叉树的所有路径 ● 404.左叶子之和 16.代码随想录day21 | ● 530.二叉搜索树的最小绝对差 ● 501.二叉搜索树中的众数 ● 236. 二叉树的最近公共祖先 203.移除链表元素
链表定义
struct ListNode
{
int val;
ListNode* next;
ListNode(): val(0), next(NULL) {};
ListNode(int x): val(x), next(NULL) {};
ListNode(int x, ListNode* next): val(x), next(next) {};
}
1.在原链表上移除链表元素
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
while(head!= NULL && head->val == val)
{
ListNode* tmp = head;
head = head->next;
delete tmp;
}
ListNode* cur = head;
while(cur != NULL)
{
if(cur->next != NULL && cur->next->val == val)
{
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
}
else
cur = cur->next;
}
return head;
}
};
为什么是
if(cur->next != NULL && cur->next->val == val)
而不是
if(cur->next->val == val)
考虑一个例子,4->5->6,
要删除6的话,到最后一步,cur->next是NULL,访问cur->next->val会报空指针错误
指针
ListNode* node;
这个node里面储存的就是地址了,所以可以有以下操作
ListNode* head
ListNode* node;
node = head
-> 和 .
箭头(->):左边必须为指针;
点号(.):左边必须为实体。
//实体
ListNode node1;
node1.val = 2;
//指针
ListNode node2;
node2->val = 2;
NULL
NULL就是传说中的空指针
delete
delete ptr -- 代表用来释放内存,且只用来释放ptr指向的内存。
ptr为指针
2.添加虚拟头结点法
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
//ListNode* dummy_head;
ListNode* dummy_head = new ListNode();
dummy_head->next = head;
ListNode* cur = dummy_head;
while(cur != NULL)
{
if(cur->next != NULL && cur->next->val == val)
{
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
}
else
cur = cur->next;
}
//return head;
return dummy_head->next;
}
};
为什么是
ListNode* dummy_head = new ListNode();
而不是
ListNode* dummy_head;
错误原因:没有实例化,而接下来的代码里要调用dummy_head里的东西,所以会报错
为什么是
return dummy_head->next;
而不是
return head;
因为之前的head有可能被释放掉了
707.设计链表
mydemo-未添加内存释放
class MyLinkedList {
public:
//结点结构体
struct LinkedNode {
int val;
LinkedNode* next;
LinkedNode(): next(NULL) {};
LinkedNode(int val):val(val), next(NULL){};
};
LinkedNode* dummyhead;
int size;
MyLinkedList() {
dummyhead = new LinkedNode(); //不要忘记实例化
size = 0;
}
int get(int index) {
LinkedNode* cur = dummyhead;
if(index>=0 && index<size)
{
while(index--)
cur = cur->next;
return cur->next->val;
}
else
return -1;
}
void addAtHead(int val) {
LinkedNode* newnode = new LinkedNode(val);
newnode->next = dummyhead->next;
dummyhead->next = newnode;
size++;
}
void addAtTail(int val) {
LinkedNode* newnode = new LinkedNode(val);
LinkedNode* cur = dummyhead;
while(cur->next != NULL)
{
cur = cur->next;
}
cur->next = newnode;
size++;
}
void addAtIndex(int index, int val) {
LinkedNode* newnode = new LinkedNode(val);
LinkedNode* cur = dummyhead;
if(index>=0 && index<=size)
{
while(index--)
{
cur = cur->next;
}
newnode->next = cur->next;
cur->next = newnode;
size++;
}
}
void deleteAtIndex(int index) {
LinkedNode* cur = dummyhead;
if(index>=0 && index<size)
{
while(index--)
{
cur = cur->next;
}
cur->next = cur->next->next;
size--;
}
}
};
/**
* Your MyLinkedList object will be instantiated and called as such:
* MyLinkedList* obj = new MyLinkedList();
* int param_1 = obj->get(index);
* obj->addAtHead(val);
* obj->addAtTail(val);
* obj->addAtIndex(index,val);
* obj->deleteAtIndex(index);
*/
mydemov2--内存释放版
void deleteAtIndex(int index) {
LinkedNode* cur = dummyhead;
if(index>=0 && index<size)
{
while(index--)
{
cur = cur->next;
}
LinkedNode* tmp = cur->next;
cur->next = cur->next->next;
size--;
//内存释放
delete tmp;
}
}
206 反转链表
1.双指针法
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = NULL;
ListNode* cur = head;
while(cur != NULL) //可以写成 while(cur)
{
ListNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
return pre;
}
};
暂存cur->next;
ListNode* temp = cur->next;
key:改变方向
cur->next = pre;
双指针向前移动(注意顺序)
pre = cur;
cur = temp;
如果顺序搞错了:
cur = temp;
pre = cur
//pre移动到的就不是cur之前的位置了,就错了
2.递归代码:
正确代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverse(ListNode* cur, ListNode* pre)
{
if(cur==NULL) return pre;
ListNode* temp = cur->next;
cur->next = pre;
return reverse(temp, cur);
}
ListNode* reverseList(ListNode* head) {
ListNode* pre = NULL;
ListNode* cur = head;
return reverse(cur, pre);
}
};
报错:C++不能函数里面定义函数
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = NULL;
ListNode* cur = head;
void reverse(ListNode* cur, ListNode* pre)
{
if(cur)
{
ListNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
}
}
reverse(cur, pre);
return pre;
}
};
Line 19: Char 13: error: function definition is not allowed here
报错:为啥这样写,所有案例的输出都是 []
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
void reverse(ListNode* cur, ListNode* pre);
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = NULL;
ListNode* cur = head;
reverse(cur, pre);
return pre;
}
};
void reverse(ListNode* cur, ListNode* pre)
{
if(cur)
{
ListNode* temp = cur->next;
cur->next = pre;
pre = cur;
cur = temp;
reverse(cur,pre);
}
}
- 链表的结构确实发生了反转,但是,reverseList函数里的pre指针并没有被重新赋值成反转链表的pre的地址。
- void reverse(ListNode* cur, ListNode* pre),这样传进去的是地址
所以可以改写成reverse(head, Null)可以更加清晰的看到传进去的是地址,所以pre并没有被重新赋值
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = NULL;
ListNode* cur = head;
//reverse(cur, pre);
reverse(head, NULL);
return pre;
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!