24. 两两交换链表中的节点
题目链接:https://leetcode.cn/problems/swap-nodes-in-pairs/description/
思路:虚拟头结点同样需要,两两交换需要设置两个tmp1、tmp2保存临时节点,边界条件也要注意,区分偶数个链表和奇数个链表。遍历指针指向做交换的两个节点的前一个节点,交换完成然后移动两个节点。有一点点绕,需要注意。
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyhead = new ListNode(0); //定义虚拟头节点
dummyhead->next = head;
ListNode* current = dummyhead;
while(current->next != nullptr && current->next->next != nullptr){ //注意边界条件,区分偶数个节点和奇数个节点的情况
ListNode* tmp = current->next; //记录current指针指向的后一个节点
ListNode* tmp1 = current->next->next->next; //记录current指针指向的第三个节点
current->next = current->next->next;
current->next->next = tmp; //下一个节点的指针指向tmp
tmp->next = tmp1;
current = current->next->next; //移动2位后准备下一步操作
}
head = dummyhead->next;
delete dummyhead;
return head;
}
};
19.删除链表的倒数第N个节点
题目链接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/
思路:删除倒数第N个节点,可用快慢指针解决;目的要求快指针与慢指针的间隔为N即可,又因为要删除节点需要知道删除节点的前驱节点,由前驱节点来操作删除事宜。所以是N+1。总的来书不难。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode* fast = dummyhead;
ListNode* slow = dummyhead;
while(n>0 && fast != nullptr){ //目的要求快指针与慢指针间隔为N
fast = fast->next;
n--;
}
fast = fast->next; //因为只有慢指针指向操作节点的前一个节点才能进行目标指针的操作
while(fast != nullptr){
fast = fast->next;
slow = slow->next;
}
ListNode* tmp = slow->next;
slow -> next = slow->next->next;
delete tmp;
return dummyhead->next;
}
};
面试题 02.07. 链表相交
题目链接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/description/
思路:该题是求两链表的交点位置;需要双指针解法,关键在于currentA和currentB在同一起点上(链表末尾对齐)。该题不难。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* currentA = headA;
ListNode* currentB = headB;
int lengthA=0,lengthB=0;
while(currentA!= NULL){
lengthA++;
currentA = currentA->next;
}
while(currentB!= NULL){
lengthB++;
currentB = currentB->next;
}
currentA = headA;
currentB = headB;
// 选择A作为最长链表的头
if(lengthB>lengthA){
swap(currentA,currentB);
swap(lengthA,lengthB);
}
int gap = lengthA-lengthB; //长度差
//让currentA和currentB在同一起点上(链表末尾对齐)
while(gap>0){
currentA = currentA->next;
gap--;
}
while(currentA!=NULL){
if(currentA == currentB){
return currentA;
}
currentA = currentA->next;
currentB = currentB->next;
}
return NULL;
}
};
142.环形链表II
题目链接:https://leetcode.cn/problems/linked-list-cycle-ii/description/
思路:环形链表,首先确定是否有环,有环再确定环的入口。环的入口可用快慢指针解决,先固定快指针每次走两格,慢指针每次走一格,这样就有数学关系2(x+y) = n(y+z)+x。其中x表示head节点到环的入口节点处,y表示环中入口到快慢节点相遇的节点的距离,z表示相遇节点到入口的距离。由数学关系得x=z,这样就根据数学关系编写代码。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {//判断链表是否有环;找到环的入口
ListNode* fast = head;
ListNode* slow = head;
while(fast !=NULL && fast->next != NULL){ //fast指针每次移动两格,确保当前节点和下一节点不为空
slow = slow->next;
fast = fast->next->next;
//快慢指针相遇并计算 slow = x+y;fast = x+n(y+z); 2(x+y) = x+n(y+z); x = (n-1)(y+z)+z
if(slow == fast){
ListNode* i = fast;
ListNode* j = head;
while(i != j){ // x=z i在x上移动j在z上移动
i = i->next;
j = j->next;
}
return j;
}
}
return NULL; //没环返回空值
}
};
707设计链表
题目链接:https://leetcode.cn/problems/design-linked-list/description/
该题还是没编译成功,需要再次花时间处理下
学习时长:5小时