力扣第四天----第24题、第19题、第142题、面试0207
文章目录
一、第24题–两两交换链表中的节点
链表的题,做到现在都是使用了dummyhead。这题中,每隔两个交换一次→设置2个临时变量存储指针,便于交换操作,再配合cur = cur->next->next移动指针。
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode* cur = dummyhead;
while((cur->next != nullptr) && (cur->next->next != nullptr)){ //这里注意,
//要把(cur->next != nullptr) 放在前面判断,通过了再判断(cur->next->next != nullptr),避免出现空指针。
ListNode* tempn1 = cur->next;
ListNode* tempn2 = cur->next->next->next;
cur->next = tempn1->next;
tempn1->next = tempn2;
cur->next->next = tempn1;
cur = cur->next->next;
}
return dummyhead->next;
}
}
二、第19题–删除链表的倒数第 N 个结点
也是用到了dummyhead。这道题类似于前几天做过的"第209题–长度最小的子数组",使用双指针的间距表达窗口长度。两个while的判定条件要注意。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode* fast = dummyhead;
ListNode* slow = dummyhead;
n++;
while(n--){ //这里要使fast移动n+1次,因为删除操作要使slow移动到第N个节点的前一节点。
fast = fast->next;
}
while(fast != nullptr){ //注意不要出现空指针,使用fast!=nullptr还是fast->next!=nullptr要注意,可以代入特殊情况试一下。
fast = fast->next;
slow = slow->next;
}
slow->next = slow->next->next;
return dummyhead->next;
}
};
三、第142题–环形链表 II
链表里遇到的最复杂的题,一共用到三个指针----用快慢指针去寻找相遇的点,用第3个指针去找循环开始的节点(结合快慢指针的结果)。
吐槽一下:判断是否是循环链表,考查的知识点就都考查到了。求循环节点起始位置的方法,就像小学数学题,没体现出新的链表知识点、也不是多高级的数学证明,也就能考查下逻辑能力。真是没意愿搞这个小学数学题,纯纯地没必要,看了下答案写上去的。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *fast = head;
ListNode *slow = head;
ListNode *chase = head;
while (fast != nullptr){ //空指针判断,如果空了,直接返回nullptr
slow = slow->next;
if (fast->next == nullptr){ //下一个节点的空指针判断,如果空了,直接返回nullptr。每次循环fast移动两次,所以要判断两个位置是否为空指针。
return nullptr;
}
fast = fast->next->next; //每次循环,快指针移动两次,慢指针移动一次,如果有循环的话就会相遇,即触发下面if条件。
if(fast == slow){
while(chase != slow){ //用第三个指针和当前的慢指针再次去相遇,如果相遇了,一定会是循环起始节点。触发跳出循环的条件,就是返回节点。
chase = chase->next;
slow = slow->next;
}
return chase;
}
}
return nullptr;
}
};
四、面试0207–链表相交
两个链表组合起来,A+B和B+A,两个指针分别从各自的head遍历,直到这两个节点相等。因为存在相交的情况,在A+B或者B+A的末端,存在相等的情况。
有一些细节要注意----一个链表为空的情况;链表循环结束,手动移动指针到另一个链表。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* nodeA = new ListNode(0);
nodeA = headA;
ListNode* nodeB = new ListNode(0);
nodeB = headB;
if((headA == nullptr) || (headB == nullptr)) //节点为空的情况处理。
return nullptr;
else{
while(nodeA!=nodeB){ //两节点不相等时一直循环下去,到最后一定会相等的。如果不存在相交情况,
//循环最后nodeA和nodeB都是nullptr,也是相等的。
if (nodeA == nullptr) //如果到了末尾,读到空指针时,手动设置nodeA的位置为headB,从另一个链表继续遍历。
nodeA = headB;
else //正常情况,没到末尾,nodeA移动到下一节点。
nodeA = nodeA->next;
if (nodeB == nullptr)
nodeB = headA;
else
nodeB = nodeB->next;
}
return nodeA;
}
}
};