24. 两两交换链表中的节点
题目链接:24. 两两交换链表中的节点
注意事项:
- 注意结点在变更时,到底需要保存几个结点的地址、
- 在第一次提交代码时,忘记设置中间变量temp1导致超时
/**
* 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) {
ListNode * nhead = new ListNode(0, head); //设置虚拟头结点
ListNode * cur = nhead;
while( cur->next != nullptr && cur->next->next != nullptr){ //注意两个条件不能颠倒
ListNode * temp = cur->next; //保存第0个结点
ListNode * temp1 = cur->next->next->next; //保存第2个位置的结点地址
cur->next = cur->next->next;
cur->next->next = temp;
cur->next->next->next = temp1; //将后续结点接到第1位置后
cur = cur->next->next; //从第2个位置结点前一个结点第1结点开始下次循环
}
head = nhead->next;
delete nhead;
return head;
}
};
19. 删除链表的倒数第 N 个结点
题目链接:19. 删除链表的倒数第 N 个结点
注意事项:
- 指针移动时需要注意到底需要找到的是哪个位置,本题目是删除,需要找到待删除的头一个结点
- 移动过程可以分成两个循环,也可以在一个循环搞定,如下
/**
* 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) {
ListNode * nhead = new ListNode(0, head);
ListNode * cur1 = nhead; //先行移动的指针
ListNode * cur2 = nhead; //后移动的指针
while(cur1->next != nullptr){
if(n <= 0){
cur2 = cur2->next; //在cur1还未到达指定位置时,cur1还不需移动
}
cur1 = cur1->next;
n--;
}
ListNode * temp = cur2->next->next;
delete cur2->next;
cur2->next = temp;
head = nhead->next;
delete nhead;
return head;
}
};
160. 相交链表
题目链接:160. 相交链表
注意事项:
- 理解解题思路,之前从来没有接触这个想法
- 每次循环的判断条件是cur != nullptr,而不是cur->next != nullptr,因为需要明确的是当前指针的存在性
- 注意相交的链表节点判断的是地址相同与否,而不是结点的val值
- 再次使用cur进行对链表的遍历时,需要再次将cur初始化成头结点地址
/**
* 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;
ListNode * curA = headA;
ListNode * curB = headB;
while(curA != nullptr){
lenA++;
curA = curA->next;
}
while(curB != nullptr){
lenB++;
curB = curB->next;
}
if(lenA < lenB){ //将A链表修改为长度最长的链表
curA = headB;
curB = headA;
swap(lenA, lenB);
}else{
curA = headA;
curB = headB;
}
int count = lenA - lenB;
while(count--){ //将两个链表对齐后向下共同遍历
curA = curA->next;
}
while(curA != nullptr){
if(curB == curA){ //如果地址相同,返回当前的地址
return curA;
}
curB = curB->next;
curA = curA->next;
}
return nullptr;
}
};
142.环形链表II
题目链接:142.环形链表II
注意事项:
- 理解思路,关键点是找到相交结点后,再次从头结点和相交结点向下遍历,再次相会的结点为链表的环形入口结点
/**
* 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) {
ListNode * slow = head;
ListNode * fast = head;
while(fast != nullptr && fast->next != nullptr){
slow = slow->next;
fast = fast->next->next;
if(slow == fast){
ListNode * cur1 = slow;
ListNode * cur2 = head;
while(cur1 != nullptr){
if(cur1 == cur2){
return cur1;
}
cur1 = cur1->next;
cur2 = cur2->next;
}
}
}
return nullptr;
}
};