程序员面试金典 02 刷题回忆录
02.01 移除重复节点
用unordered_set查重即可
02.02 返回倒数第k个节点
快慢指针
02.03 删除中间节点
一般情况下要用多个指针,但是可以直接消灭后一个,也算删除。
杀不掉我,我就变成你,然后再干掉你,就等于杀死了自己。
class Solution {
public:
void deleteNode(ListNode* node) {
node->val = node->next->val;
node->next = node->next->next;
}
};
02.04 分割链表
直接新开俩链表,暴力循环即可。
虚拟头节点,练习一下python
class Solution:
def partition(self, head: ListNode, x: int) -> ListNode:
dummy1, dummy2 = ListNode(), ListNode()
cur1,cur2, cur = dummy1, dummy2, head
while cur:
if cur.val < x:
cur1.next = cur
cur1 = cur1.next
else:
cur2.next = cur
cur2 = cur2.next
cur = cur.next
cur1.next, cur2.next = dummy2.next, None
return dummy1.next
02.05 链表求和
暴力求解即可
02.06 回文链表
这个比较有意思
先用快慢指针将链表分成两段,再将后一段链表翻转。之后依次比较即可。
class Solution {
public:
bool isPalindrome(ListNode* head) {
if ( !head ) return true;
ListNode* fast = head->next, *slow = head;
while( fast && fast->next ){
fast = fast->next->next;
slow = slow->next;
}
// slow->next是后半段的链表的head 长度为5的话,slow在第三个,拆一下,32
// 把后半段翻转
ListNode* pre=NULL, *cur=slow->next, *sav;
while(cur){
sav = cur->next;
cur->next = pre;
pre = cur;
cur = sav;
}
// 翻转结束
// pre就是翻转后的head
cur = pre;
fast = head;
while(cur&&fast&&cur->val==fast->val){
cur = cur->next;
fast = fast->next;
}
bool res = cur==NULL;
// 还原链表
/*
cur = pre;
pre = NULL;
while(cur){
sav = cur->next;
cur->next = pre;
pre = cur;
cur = sav;
}
slow->next = pre;
*/
return res;
}
};
02.07 链表相交
这题真nb,凡是数学题都nb
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode *h1=headA, *h2=headB;
while(h1!=h2)
{
h1=h1==nullptr? headB: h1->next;
h2=h2==nullptr? headA: h2->next;
}
return h1;
}
};
设交集链表长c,链表1除交集的长度为a,链表2除交集的长度为b,有
a + c + b = b + c + a
若无交集,则a + b = b + a
02.08 环路检测
常考
可以参考严格的数学证明
https://leetcode-cn.com/problems/linked-list-cycle-lcci/solution/kuai-man-zhi-zhen-zheng-ming-bi-jiao-yan-jin-by-ch/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *slow = head, *fast = head;
while (fast != nullptr) {
slow = slow->next;
if (fast->next == nullptr) {
return nullptr;
}
fast = fast->next->next;
if (fast == slow) { //当快慢指针相遇后
ListNode *ptr = head;
while (ptr != slow) {
ptr = ptr->next;
slow = slow->next;
}
return ptr;
}
}
return nullptr;
}
};