这几天实验室师哥毕业,事有点多
创建虚拟头节点,不断的循环直到链表结束,使用暂存节点保存第一个数据,再把第一个数据插入到第二个数据后,之后更改头节点为暂存节点即可,难度不高。
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* cur = dummyHead;
while (cur) {
ListNode* tmp;
if (cur->next) tmp = cur->next;
if (tmp->next) {
cur->next = tmp->next;
tmp->next = cur->next->next;
cur->next->next = tmp;
cur = tmp;
}
else return dummyHead->next;
}
return dummyHead->next;
}
};
暴力解法先遍历节点数目,再找到待删除节点的前一节点进行删除即可
题目进阶要求只能遍历一次节点,题解的思路很巧妙,双指针结合进链表中,建立虚拟头节点,fast先移动n次,之后fast和slow同时移动直到fast为空,此时slow指向即为待删除节点的前一节点,进行删除即可,记得delete(下述代码没写)
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* fast = dummyHead;
ListNode* slow = dummyHead;
while (n && fast) {
fast = fast->next;
n--;
}
while (fast->next) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return dummyHead->next;
}
};
经典题,两个链表list1,list2,创建两个指针,依次遍历list1和list2,谁先指向null谁就重新指向另一个链表,知道两个指针相遇,此时相遇要么指向相交节点,要么指向null,指向null则代表两个链表没有相交
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* p1 = headA;
ListNode* p2 = headB;
while (p1 != p2) {
if (p1 != NULL) p1 = p1->next;
else p1 = headB;
if (p2 != NULL) p2 = p2->next;
else p2 = headA;
}
return p1;
}
};
非常好的一道题目,之前做过一遍,还是没什么印象。分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。fast指针一定先进入环中,如果fast指针和slow指针相遇的话,一定是在环中相遇,这是毋庸置疑的。一旦相遇,slow重新指向头指针,并且slow和fast修改移动速度,二者均每次移动一个节点,直至下次相遇的节点处即为环入口。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast != NULL && fast->next != NULL) {
slow = slow->next;
fast = fast->next->next;
// 快慢指针相遇,此时从head 和 相遇点,同时查找直至相遇
if (slow == fast) {
ListNode* index1 = fast;
ListNode* index2 = head;
while (index1 != index2) {
index1 = index1->next;
index2 = index2->next;
}
return index2; // 返回环的入口
}
}
return NULL;
}
};
总结:19和142还要重点标记。