leetcode24两两交换链表中的结点
我的思路见图,一开始没有设置虚拟头结点,画图画了几遍,发现还是要设置一个虚拟头结点,另外,最后返回的不能是head,因为此时head已经不在链表首位,而是变成了链表第二位。
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* cur = head;
ListNode* tmp;
ListNode* pre = new ListNode(0);
pre->next = cur;
ListNode* q = pre;
while(cur && cur->next){
pre->next = cur->next;
tmp = cur->next->next;
cur->next->next = cur;
cur->next = tmp;
pre = cur;
cur = tmp;
}
head = q->next;
delete q;
return head;
}
};
看了卡尔哥的解析,还是解析的图和代码更简洁直观,也更有逻辑,特别是要学学怎么好好画图,感觉图画得好,思路也更清晰
leetcode19删除列表的倒数第N个结点
这一题我一开始用的笨方法先遍历链表得到链表的长度,然后找倒数第N个,很麻烦而且明显这不是考察的意图。
正确方法是设置两个指针,一个快指针一个慢指针,快指针在慢指针后面的n+1步。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode* slow = dummyhead;
ListNode* fast = dummyhead;
for(int i = 0; i < n; i++){
fast = fast->next;
}
while(fast->next){
fast = fast->next;
slow = slow->next;
}
ListNode* q = slow->next;
slow->next = slow->next->next;
delete q;
return dummyhead->next; // 最后千万不要返回head,因为head可能被删除了
}
};
解析里是这样的,实际上是让fast移动到带虚拟头结点的第n+2位,原链表的第n+1位,当fast移动到null时,slow正好在倒数n+1位
while表达式是先判断n,再自减
while(n-- && fast != NULL) {
fast = fast->next;
}
fast = fast->next; // fast再提前走一步,因为需要让slow指向删除节点的上一个节点
while (fast != NULL) {
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
面试题02.07链表相交
这一题通过看图可以观察出规律,求出两个链表的长度并求出差值,假设A比B长, 让指针A移动到和指针B末尾对齐,也就是让A指向链表的长度和B相同,A和B同时向后移动,比较A和B是否,相同的位置就是相交的位置。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int nA = 0;
int nB = 0;
int n;
ListNode* tmpA = headA;
ListNode* tmpB = headB;
while(tmpA){
nA++;
tmpA = tmpA->next;
}
while(tmpB){
nB++;
tmpB = tmpB->next;
}
tmpA = headA;
tmpB = headB;
if(nA >= nB){
n = nA - nB;
while(n--){
tmpA = tmpA->next;
}
while(tmpB && tmpA != tmpB){ // 首先要保证短的那一个不是null
tmpA = tmpA->next;
tmpB = tmpB->next;
}
return tmpB; // 返回短的那一个,即使没有交点,最后也能返回null
}
else{
n = nB - nA;
while(n--){
tmpB = tmpB->next;
}
while(tmpA != tmpB){
tmpA = tmpA->next;
tmpB = tmpB->next;
}
return tmpA;
}
}
};
解析为了让curA始终指向长的那个链表,是这样的
if (lenB > lenA) {
swap (lenA, lenB);
swap (curA, curB);
}
leetcode142环形链表
fast走两步,slow走一步,最后fast和slow会在环内相遇
证明如下:
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast && fast->next){ // 即使只有一个结点,如果有环,就不可能存在空指针
fast = fast->next->next;
slow = slow->next;
if(fast == slow){
ListNode* index1 = fast;
ListNode* index2 = head;
while(index1 != index2){
index1 = index1->next;
index2 = index2->next;
}
return index2;
}
}
return NULL;
}
};