Leetcode 160. 相交链表
解题思路:
代码实现:时间复杂度O(n+m) 空间复杂度O(1)
我的实现方式
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* pa = headA, *pb = headB;
bool f1 = false, f2 = false;
while(pa != nullptr && pb != nullptr){
if(pa == pb) return pa; // 必须放在前面,否则当两个链表第一个节点就是相交结点的话,则会被跳过
pa = pa -> next;
pb = pb -> next;
if(pa == nullptr && !f1) pa = headB, f1 = true;
if(pb == nullptr && !f2) pb = headA, f2 = true;
}
return nullptr;
}
};
更加优雅的方式:(为什么不会死循环,因为A和B在交换链表遍历之后,一定会在同一时刻(不相交的话)变成nullptr)(即同时走了a+b长度的路)
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *A = headA, *B = headB;
while (A != B) {
A = A != nullptr ? A->next : headB;
B = B != nullptr ? B->next : headA;
}
return A;
}
};
Leetcode 206. 反转链表(板子)
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* pre = nullptr, * cur = head, *nxt = head;
while (nxt != nullptr){
nxt = nxt -> next;
cur -> next = pre;
pre = cur, cur = nxt;
}
return pre;
}
};
Leetcode 92. 反转链表 II
利用规律:在反转结束后,从原链表上看,pre指向这一段的末尾(即反转后链表的头),cur指向这一段的下一个节点。
思路:
蓝色线是先按照206的解法翻转链表,粉线是接下来与整个链表对接的操作。
为了统一操作(left = 1的情况),设置一个头结点。
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
ListNode* dummy = new ListNode(0, head); // 初始化虚拟头结点(统一left=1的情况)
ListNode* p0 = dummy, *pre = nullptr, * cur, * nxt;
// 找出p0
for(int i = 0; i < left - 1; i ++) p0 = p0 -> next;
cur = p0 -> next, nxt = cur;
// 开始翻转(那一部分(子链表),最后再进行与整体链表的对接)
for(int i = 0; i < right - left + 1; i ++){ // 子链表花费right - left + 1次翻转
nxt = nxt -> next;
cur -> next = pre;
pre = cur, cur = nxt;
}
// 翻转完毕, 此时pre是当前子链表的'head', cur指向大链表中子链表的后一个结点(拼接)
p0 -> next -> next = cur;
p0 -> next = pre;
return dummy -> next; // dummy的next结点才是真正的头结点
}
};