复习
虚拟头节点创建内存与指针示意图:
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* cur = dummyHead;
一、题
1. 24 两两交换链表中的节点
交换和删除节点的题把交互的过程画出来,边画边写。
步骤:
temp = cur->next; temp1 = cur->next->next->next;
1、cur->next = cur->next->next;
2、cur->next->next = temp;
3、temp->next = temp1; 或是 cur->next->next->next = temp1;
4、cur = cur->next->next;
注意:
1、while循环的条件,偶数和奇数的情况
while(cur->next != NULL && cur->next->next != NULL) 为什么是 && 不是 || ??
2、为什么要使用temp指针保存节
2. 19 删除链表的倒数第N个节点
不好想,想到了很简单。记得使用快慢双指针,慢指针指向的应该是倒数N+1个节点。
3. 面试题 02.07. leetcode160 链表相交
思路:使用哈希映射insert函数保存节点指针,再用count函数查找是否有相同指针地址。
想到用unordered_set<ListNode*> visited这道题非常简单。
PS:链表相交说明两个链表中有两个指针(Alistnode、Blistnode)指向了同一片内存
Alistnode->val == Blistnode->val
4. 142 环形链表II
判断链表是否有环,
思路一:使用哈希映射查找相同指针地址,因为环入口节点一定有两个不同的指针指向这个入口节点
ListNode* detectCycle(ListNode* head) {
unordered_set<ListNode*> visited;
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* temp = dummyHead;
temp = temp->next;
while (temp != NULL) {
visited.insert(temp);
temp = temp->next;
if (visited.count(temp)) {
// ListNode* found = head;
// int pos = 0;
// while(found != temp){
// pos++;
// found = found->next;
// } pos:第pos个节点开始环
return temp;
}
}
return NULL;
}
思路2:进阶,使用快慢双指针让空间复杂度为O(1)
快指针每次nextnext,慢指针每次next,如果快慢指针相遇则说明链表有环,并且可以证明:无论如何,慢指针还没走完一圈,快指针就会追上慢指针,而x = z + n*圈,这样来找到入口
其实代码非常简单,不需要去计数,核心就是x=z,相遇处一个index,起点一个index1,两个index一直next,直到相遇则return index
总结
三种题型
1、删除链表节点,也就是说让a->next = a->next->next
2、反转链表节点,三个步骤,每个步骤记得画图,和保存temp节点
3、寻找链表中是否有多个指针指向同一内存空间,unordered_set的insert和count
PS:
快慢指针的辅助使用:19 删除链表的倒数第N个节点、142 环形链表II