24. 两两交换链表中的节点
题目链接: 24. 两两交换链表中的节点
思路: 利用虚拟头结点保证链表的头不变,分别找到要交换的两个节点,依次交换位置(注意交换的顺序很重要,不然会断链)
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
auto dummy = new ListNode(0);
dummy->next = head;
for(auto p = dummy;p->next && p->next->next;){//循环条件一定要这样,否则会出现访问异常或者runtime error
auto a = p->next, b = a->next;//找到要交换的结点
p->next = b;
a->next = b->next;
b->next = a;
p = a;
}
return dummy->next;
}
};
总结我自己写题过程中的问题:
- for循环若是没有在开始写递进语句,则在下面一定要补上,且谁的for循环谁在变,不要乱变变量(for循环需要加强练习,感觉写带码的本质是将自己的思维转化成代码的过程)
- &&与|| ,其中 &&是左边不成立则不判断右边的语句(因此我们写判断条件时要注意先后顺序),||则是两边都要判断。
19. 删除链表的倒数第 N 个结点
题目链接: 19. 删除链表的倒数第 N 个结点
思路: 首先记录下链表的长度,再用总长度减去倒数点,其删除时我们必须先找到被删除的前一个结点,及len - index - 1 的位置才行
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
**/
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
auto dummy = new ListNode(0);
dummy->next = head;
int len = 0;
for(auto p = dummy; p->next; p = p->next) len++;
int index = len - n - 1;
auto q = dummy;
for(int i = 0; i <= index;i++) q = q->next;
auto temp = q->next->next;
q->next = temp;
return dummy->next;
}
};
面试题 02.07. 链表相交
题目链接: 面试题 02.07. 链表相交
思路1: (暴力求解),利用两层循环,每层每层的找,直到找到相等的点。
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
auto dummy1 = new ListNode(-1);
auto dummy2 = new ListNode(-1);
dummy1->next = headA;
dummy2->next = headB;
auto p = dummy1;
auto q = dummy2;
for(p = dummy1; p->next; p = p->next){
for(q = dummy2; q->next; q = q->next){
if(p->next == q->next) return p->next;
}
}
if(p->next != q->next) return NULL;
else return p->next;
}
};
思路2: 若是两个链表相交则他们后面的结点一定是一样的,因此我们可以先将两者的长度的差值求出来,然后将两者中长度较长的向后移动差值的位置,使两者对齐,再依次判断每一个是否相等。
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
int lenA = 0, lenB = 0;
for(auto p = headA; p ;p = p->next) lenA++;
for(auto q = headB; q ;q = q->next) lenB++;
int dec;
auto tempA = headA, tempB = headB;
if(lenA > lenB) {
dec = lenA -lenB;
for(int i = 1; i <= dec; i++) tempA = tempA->next;
while(tempA && tempB){
if(tempA == tempB) return tempA;
else{
tempA = tempA->next;
tempB = tempB->next;
}
}
}
else {
dec = lenB -lenA;
for(int i = 1; i <= dec; i++) tempB = tempB->next;
while(tempA && tempB){
if(tempA == tempB) return tempA;
else{
tempA = tempA->next;
tempB = tempB->next;
}
}
}
if(tempA != tempB) return NULL;
else return tempA;
}
};
142. 环形链表 II
题目链接: 142. 环形链表 II
本题主要学习链表中快慢指针的思路
思路: 判断两者是否有环,让slow指针每次走一步,让fast指针每次走两步,若是有环由于速度差则两者一定会在某一点处相遇,我们可以利用快慢指针找到相遇点。
前置题目链接: 141. 环形链表
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
if(!head || !head->next) return false;
auto slow = head, fast = slow -> next;
while(fast){
slow = slow->next, fast = fast->next;
if(!fast) return false;
fast = fast->next;
if(slow == fast) return true;
}
return false;
}
};
本题:
代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
if(!head || !head->next) return NULL;
auto slow = head, fast = slow -> next;
while(fast){
slow = slow->next, fast = fast->next;
if(!fast) return NULL;
fast = fast->next;
if(slow == fast){
slow = head;
while(slow != fast->next){
slow = slow->next;
fast = fast->next;
}
return slow;
}
}
return NULL;
}
};
注: 一定要自己动手推一推公式和过程,才能更好的理解(不要懒)。