24.两两交换链表中的节点
题解
ListNode* swapPairs(ListNode* head) {
ListNode *dumyhead = new ListNode(0, head);
ListNode *cur = dumyhead;
ListNode *temp = nullptr;
ListNode *temp1 = nullptr;
while (cur->next && cur->next->next) {
temp = cur->next;
cur->next = cur->next->next;
temp1 = cur->next->next;
cur->next->next = temp;
temp->next = temp1;
cur = cur->next->next;
}
head = dumyhead->next;
delete dumyhead;
return head;
}
总结
依旧引入虚拟头结点保证操作统一,另外注意改变链表结点指向时,提前保存下一次循环需要的结点指针。
19.删除链表的倒数第N个结点
题解
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode *dumyhead = new ListNode(0, head);
ListNode *fast = dumyhead;
ListNode *slow = dumyhead;
int count = n + 1;
while (count--) fast = fast->next;
while (fast) {
fast = fast->next;
slow = slow->next;
}
ListNode *temp = slow->next;
slow->next = slow->next->next;
delete temp;
head = dumyhead->next;
delete dumyhead;
return head;
}
总结
双指针法,fast先走n步后slow指针出发,然后fast指空时,slow指向需要被删除的结点。
02.07.链表相交
题解
int get_length(ListNode *head) {
if (!head) return 0;
int count = 0;
ListNode *cur = head;
while (cur) {
cur = cur->next;
count++;
}
return count;
}
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (headA == nullptr || headB == nullptr) return nullptr;
ListNode *dumyhead1 = new ListNode(0, headA);
ListNode *dumyhead2 = new ListNode(0, headB);
int A_length = get_length(headA);
int B_length = get_length(headB);
int cap = abs(A_length - B_length);
ListNode *first_move = (A_length >= B_length)? dumyhead1: dumyhead2;
ListNode *second_move = (first_move == dumyhead1)? dumyhead2: dumyhead1;
while (cap--) first_move = first_move->next;
while (first_move && first_move->next != second_move->next) {
first_move = first_move->next;
second_move = second_move->next;
}
return first_move->next;
}
总结
将两个链表各遍历一次,获得两个链表的长度,然后让first指向更长的链表头结点,让其先开始移动,将长度差消除,此时first指针跟second指针对齐以后,开始循环判断是否指向头一个结点,如果指向同一个结点,则为交点结点。
142.环形链表二
题解
ListNode *detectCycle(ListNode *head) {
ListNode *fast = head;
ListNode *slow = head;
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) {
ListNode *index1 = fast;
ListNode *index2 = head;
while (index1 != index2) {
index1 = index1->next;
index2 = index2->next;
}
return index1;
}
}
return nullptr;
}
总结
算法背后的数学原理还没有搞清楚,先背下来这种算法吧。后面再花时间理解一下数学原理。
链表总结
1.虚拟头结点可以方便链表统一操作,我不使用虚拟头结点,算法总是对只含一个结点的case ac不了,很烦。
2.双指针法在链表这里也挺好用的,但要搞懂指针指向的含义,指针更新的逻辑。
3.其实408统考算法题出过跟19题一模一样的题目。