24. 两两交换链表中的节点
学习资料
题目链接/文章讲解/视频讲解: 代码随想录
代码
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
if(head == nullptr || head->next == nullptr) return head;
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* temp = dummyHead;
ListNode* store1 = nullptr;
ListNode* store2 = nullptr;
while(temp->next != nullptr && temp->next->next != nullptr){
store1 = temp->next;
store2 = temp->next->next;
store1->next = store2->next;
temp->next = store2;
store2->next = store1;
temp = store1;
}
head = dummyHead->next;
delete dummyHead;
return head;
}
};
代码
看解析之前自己想的解法,需要先遍历一遍获取长度size后,再根据给定的位置计算需要删除的节点索引Index值,最后删除该节点。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if(head == nullptr) return nullptr;
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
int size = 0;
ListNode* temp = dummyHead;
while(temp->next != nullptr){
temp = temp->next;
size++;
}
temp = dummyHead;
int index = size - n;
while(true){
if(index < 1 || index > size - 1) break;
index--;
temp = temp->next;
}
ListNode* store = temp->next;
if(n == 1){
temp->next = nullptr;
delete store;
}
else{
temp->next = temp->next->next;
delete store;
}
head = dummyHead->next;
delete dummyHead;
return head;
}
};
快慢指针可以只遍历一次链表就搞定删除操作,并且发现并不需要单独对删除尾结点进行特殊处理
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
if(head == nullptr) return nullptr;
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* fast = dummyHead;
ListNode* slow = dummyHead;
for(int i = 0; i < n + 1; i++){
fast = fast->next;
}
while(fast != nullptr){
fast = fast->next;
slow = slow->next;
}
ListNode* store = slow->next;
slow->next = slow->next->next;
delete store;
head = dummyHead->next;
delete dummyHead;
return head;
}
};
代码
以前做过,判定相交两种思路,一是哈希集合,二是看两个链表最后一个节点地址是否一致。此题双指针法可以更简单一点
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if(headA == nullptr || headB == nullptr){
return nullptr;
}
ListNode* tempA = headA;
ListNode* tempB = headB;
while(tempA != tempB){
tempA = tempA != nullptr ? tempA->next : headB;
tempB = tempB != nullptr ? tempB->next : headA;
}
return tempA;
}
};
代码
先通过哈希集合判定是否有环,再通过快慢指针找到起始入环节点
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(!isCycle(head)) return nullptr;
ListNode* slow = head;
ListNode* fast = head;
do{
slow = slow->next;
fast = fast->next->next;
}
while(slow != fast);
fast = head;
while(slow != fast){
slow = slow->next;
fast = fast->next;
}
return slow;
}
bool isCycle(ListNode *head){
if(head == nullptr || head->next == nullptr){
return false;
}
unordered_set<ListNode*> visited;
ListNode* temp = head;
while(temp->next != nullptr){
if (visited.count(temp)) {
return true;
}
visited.insert(temp);
temp = temp->next;
}
return false;
}
};
看过解析后发现我自己上面的解法有点幽默了,用哈希的话其实就已经不用快慢指针了,用快慢指针的话其实已经可以判断是否有环了,优化修改一下
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(head == nullptr || head->next == nullptr){
return nullptr;
}
ListNode* slow = head;
ListNode* fast = head;
while(fast != nullptr && fast->next != nullptr){
slow = slow->next;
fast = fast->next->next;
if(slow == fast){
fast = head;
while(slow != fast){
slow = slow->next;
fast = fast->next;
}
return slow;
}
}
return nullptr;
}
};