题目一
看到题目的第一想法:
1、需要交换,那必然要想到用临时节点作为交换存储
2、有奇、偶差别, 必然会有终止条件的不同
整理了一下流程,没想到特别好的方法,直接看了题解
看了代码随想录的想法:
有几个点得到了验证,需要注意的是:
1、题目有提到,返回头节点,感觉也是暗示用虚拟头节点
2、需要注意current和虚拟头节点,是直接=head,还是=head->next,老是会混乱
3、以后只认虚拟头节点的套路
实现时的困难:
调整了好几次,主要是:
1、缓存哪个节点
2、缓存节点后的交换顺序是怎样的
总的来说,缓存,交换顺序这些都是比较常见的,感觉这一块有点生疏,绝对需要记一个模版.
ListNode* swapPairs(ListNode* head) {
ListNode* dynamic = new ListNode(0);
dynamic->next = head;
ListNode* cur = dynamic;
while(cur->next!=nullptr && cur->next->next!=nullptr){
ListNode* temp = cur->next;//会把链表关系一并赋予
cur->next = cur->next->next;
temp->next = cur->next->next;
cur->next->next = temp;
cur = cur->next->next;
}
return dynamic->next;//注意要返回头节点才能是一个完整的链表呀,而且这里这也验证了虚拟头节点的好处..
}
题目二
看到题目的第一想法:
思路是先把链表反转,然后从head一路next直到找到n,在n-1时使得该节点等于current,然后再用常规的删除next节点的方法.但是题目有问到能不能只扫描一次?
看了代码随想录的想法:
啊soory,没有想到经典的双指针,肯定是数组刷完没有好好总结5555..也没有对经典解法和经典套路做总结5555....
1、使用虚拟头节点,不需要判断头节点,达到统一操作
2、快慢指针实际是形成一个窗口,倒数第n个与最后一个的差额是n,快慢指针一起形成差额n,也能达到这个效果 //todo 总结一下碰到过多少快慢指针的
3、删除必须要令指针指向被删除指针的前一个节点;
实现时的困难:
1、快慢指针的定义(用ListNode还是?)
答:ListNode...
2、注意while的结束条件(虽然说我经常还会debug一下看看对不对)
3、虚拟节点定义完不要老漏了next=head呢;
题目三
看到题目的第一想法:
奇怪的题....... 直接被这例子误导了
能否设计一个时间复杂度 O(n)
、仅用 O(1)
内存的解决方案?
看了代码随想录的想法:
有点像变种的快慢指针,针对的不同对象,为什么又没有想到...
实现时的困难:
1、注意这里要自己求长度
2、由哪个列表先next.可以简洁一些
if (n > m) { //这里会有更好的办法吗
/*** 强行让A保持是最长的
* // 让curA为最长链表的头,lenA为其长度
if (lenB > lenA) {
swap (lenA, lenB);
swap (curA, curB);
}
*/
diff = n - m;
curA = headA;
while(diff-- !=0){
curA = curA->next;
}
} else {
diff = m - n;
curB = headB;
while(diff-- !=0){
curB = curB->next;
}
}
3、指向相同?
这道题应该是有点奇怪的,看了一下代码随想录,只提到不是比较值相同,而是指向相同,再看了一下评论区,对指向相同有了更多的理解.
下面这个图的情况不会有,这个图搞得我一直在想,如果前面相交了,后面又分叉了,该怎么办?
但实际这样想就又回到“题目要求的是指向相同,而不是值相同”的误区.
更简洁的解法:
如何检测相交
要检测两个单链表是否相交,通常使用的方法是使用两个指针分别从两个链表的头节点开始遍历。当一个指针到达链表末尾时,让它跳到另一个链表的头节点继续遍历。如果两个链表相交,那么这两个指针最终会相遇在同一节点上;如果不相交,那么它们永远不会指向相同的内存地址。
一旦某个节点相同,那么后面的链表部分也必然相同,如下面,这个如果head链表和headB中3开始相同,那next..... next->next->next... 这一坨都是一样的,所以不会出现后面又开始分叉的情况
// Create a linked list: 1 -> 2 -> 3 -> 4 -> 5
ListNode *head = new ListNode(1);
head->next = new ListNode(2);
head->next->next = new ListNode(3);
head->next->next->next = new ListNode(4);
head->next->next->next->next = new ListNode(5);
ListNode *headB = new ListNode(6);
headB->next = new ListNode(7);
headB->next->next = new ListNode(3);
headB->next->next->next = new ListNode(4);
headB->next->next->next->next = new ListNode(5);
贴个通义千问回答
更简洁的解法:
如何检测相交
要检测两个单链表是否相交,通常使用的方法是使用两个指针分别从两个链表的头节点开始遍历。当一个指针到达链表末尾时,让它跳到另一个链表的头节点继续遍历。如果两个链表相交,那么这两个指针最终会相遇在同一节点上;如果不相交,那么它们永远不会指向相同的内存地址。
#include <iostream>
// Definition for singly-linked list.
struct ListNode {
int val;
ListNode *next;
ListNode(int x) : val(x), next(nullptr) {}
};
// Function to detect intersection point in two linked lists.
ListNode* getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *pA = headA, *pB = headB;
while (pA != pB) {
pA = pA != nullptr ? pA->next : headB;
pB = pB != nullptr ? pB->next : headA;
}
return pA;
}
// Function to print the linked list
void printList(ListNode* head) {
while (head != nullptr) {
std::cout << head->val << " ";
head = head->next;
}
std::cout << std::endl;
}
int main() {
// Create two linked lists: A and B
ListNode* A = new ListNode(1);
A->next = new ListNode(2);
A->next->next = new ListNode(3);
ListNode* B = new ListNode(4);
B->next = new ListNode(5);
// Create common part
ListNode* common = new ListNode(6);
A->next->next->next = common;
B->next->next = common;
common->next = new ListNode(7);
// Detect intersection point
ListNode* intersection = getIntersectionNode(A, B);
if (intersection != nullptr) {
std::cout << "Intersection at node with value: " << intersection->val << std::endl;
} else {
std::cout << "No intersection." << std::endl;
}
// Clean up the memory
ListNode* temp;
while (A != nullptr) {
temp = A;
A = A->next;
delete temp;
}
while (B != nullptr) {
temp = B;
B = B->next;
delete temp;
}
while (common != nullptr) {
temp = common;
common = common->next;
delete temp;
}
return 0;
}
题目四
看到题目的第一想法:
成环其实不存在必要条件.
看到这种存在前后差距的,马上能想到快慢指针,快慢指针精髓在于快多少步// todo 之前碰到的题目是怎么讲来着,总结总结....
只能想到快一整个链表?
定义快慢指针,每次都让快指针比慢指针快一步,然后让快指针循环到最后,判断一下快指针的next是否是等于慢指针所在的节点.
看了代码随想录的想法:
初步看了一下思路,很确定以前见过这个题,但我就是忘了..... - -
细节还挺多的,总的来说就是让快指针先走一步//总结一下碰到的快慢指针
实现时的困难:
1、这道题比较经典,而我只能把思路背下来了