代码随想录算法训练营第四天| 24. 两两交换链表中的节点, 19.删除链表的倒数第N个结点,面试题02.07.链表相交,142.环形链表Ⅱ
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. 二叉树的最近公共祖先 24. 两两交换链表中的节点
mydemo(超时)
/**
* 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* swapPairs(ListNode* head) {
ListNode* dummy = new ListNode();
dummy->next = head;
ListNode* cur = dummy;
ListNode* tmp1 = cur->next;
ListNode* tmp2;
ListNode* tmp3;
if(tmp1 != NULL)
{
tmp2 = tmp1->next;
if(tmp2 != NULL)
tmp3 = tmp2->next;
else
tmp3 = NULL;
}
else
{
tmp2 = NULL;
tmp3 = NULL;
}
while(cur->next != NULL || cur->next->next != NULL)
{
tmp2->next = tmp1;
tmp1->next = tmp3;
cur->next = tmp2;
cur = tmp2;
}
return dummy->next;
}
};
mydemo2
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummy = new ListNode();
dummy->next = head;
ListNode* cur = dummy;
ListNode* tmp;
while(cur->next != NULL || cur->next->next != NULL)
{
tmp = cur->next;
cur->next = cur->next->next;
tmp->next = cur->next->next;
cur->next->next = tmp;
cur = cur->next;
}
return dummy->next;
}
};
报错,tmp->next = cur->next->next;这一行报了空指针错误
Line 25: Char 36: runtime error: member access within null pointer of type 'ListNode' (solution.cpp)
两个错误
//while(cur->next != NULL || cur->next->next != NULL)
while(cur->next != NULL && cur->next->next != NULL)
tmp = cur->next;
cur->next = cur->next->next;
tmp->next = cur->next->next;
cur->next->next = tmp;
//cur = cur->next;
cur = cur->next->next;
关于指针的一点思考
指向 = 地址
ListNode* curl = new ListNode(0);
ListNode* head = new ListNode(1);
curl->next = head;
此时,curl->相当于指向,head相当于地址
直观来看,就是改变箭头指向的终点
19. 删除链表的倒数第N个结点
mydemo 暴力法
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode();
dummy->next = head;
ListNode* cur = dummy;
int len = 0;
int i = 0;
while(cur->next)
{
cur = cur->next;
len++;
}
cur = dummy;
while(i<len-n)
{
cur = cur->next;
i++;
}
ListNode* tmp = cur->next;
cur->next = cur->next->next;
delete tmp;
return dummy->next;
}
};
双指针法
思路:要删倒数第N个元素,那就先让快指针走N步,再让快慢指针一起动,当快指针到达末尾时,满指针也就到达了要删除的地方
细节:为了删除节点,慢指针应当到达要删除节点的前一个节点处,所以快指针应当先走N+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* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummy = new ListNode();
dummy->next = head;
ListNode* fast = dummy;
ListNode* slow = dummy;
n++;
while(n-- && fast!=NULL) //fast!=NULL 防止空指针错误
{
fast = fast->next;
}
while(fast)
{
slow = slow->next;
fast = fast->next;
}
if(slow->next!=NULL) //防止空指针错误
{
ListNode* tmp = slow->next;
slow->next = slow->next->next;
delete tmp;
}
return dummy->next;
}
};
面试题 02.07. 链表相交
mydemo 暴力遍历法——成功
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* fast = headA;
ListNode* slow;
while(fast)
{
slow = headB; //每次遍历之前,先回到起点
while(slow)
{
if(fast == slow)
{
return fast;
}
slow = slow->next;
}
fast = fast->next;
}
return NULL;
}
};
注意,在每次遍历前需要先回到起点
slow = headB; //每次遍历之前,先回到起点
相减法——(代码随想录)
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(headA==NULL || headB==NULL) return NULL;
int lenA = 0;
int lenB = 0;
ListNode* cura = headA;
ListNode* curb = headB;
//求A链表的长度
while(cura != NULL)
{
cura = cura->next;
lenA++;
}
//求B链表的长度
while(curb != NULL)
{
curb = curb->next;
lenB++;
}
//找出长链和短链
int lenMax = lenA > lenB? lenA : lenB;
int lenMin = lenA <= lenB? lenA : lenB;
ListNode* headMax = lenA > lenB? headA : headB;
//ListNode* headMin = lenA < lenB? headA : headB;
ListNode* headMin = lenA <= lenB? headA : headB;
ListNode* curMax = headMax;
ListNode* curMin = headMin;
//移动curMax
curMax = headMax;
for(int i=0; i<lenMax-lenMin; i++)
curMax = curMax->next;
//找交叉点
while(curMax != NULL)
{
if(curMax==curMin) return curMax;
curMax = curMax->next;
curMin = curMin->next;
}
return NULL;
}
};
一个隐藏的坑:
为什么不能写成注释里的样子?
ListNode* headMax = lenA > lenB? headA : headB;
//ListNode* headMin = lenA < lenB? headA : headB;
ListNode* headMin = lenA <= lenB? headA : headB;
考虑一种特殊情况:当lenA=lenB时,则headMax = headB, headMin = headB,两个都一样了。所以不能写成注释里的样子
不过,当要赋的值时常数则无所谓,相等就相等呗
int lenMax = lenA > lenB? lenA : lenB;
int lenMin = lenA < lenB? lenA : lenB;
但是为了安全起见,以后统一写成:
int lenMax = lenA > lenB? lenA : lenB;
int lenMin = lenA <= lenB? lenA : lenB;
142.环形链表Ⅱ
mydemo——(成功)
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* slow= head;
ListNode* fast = head;
ListNode* index1 = head;
ListNode* index2;
//判断有无环,若有环则求出相遇点
do{
if(fast == NULL || fast->next == NULL)
return NULL;
else
{
fast = fast->next->next;
slow = slow->next;
}
}
while(fast != slow);
//求出环的入口
index2 = fast;
while(index1 != index2)
{
index1 = index1->next;
index2 = index2->next;
}
return index1;
}
};
小心一个坑,do-while语句最后是有一个 ;的;
do{
}
while();
卡哥demo
思路一致,但是卡哥的写法更简洁
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* slow= head;
ListNode* fast = head;
ListNode* index;
while(fast != NULL && fast->next != NULL)
{
fast = fast->next->next;
slow = slow->next;
if(fast==slow)
{
ListNode* index = fast;
while(head != index)
{
head = head->next;
index = index->next;
}
return index;
}
}
return NULL;
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!