打卡第四天
24.两两交换链表中的节点
C++中的指针是存储了一个地址,用指针给另外一个指针赋值,就是把地址给它了。
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
// 设置虚拟头节点
ListNode* dummyHead = new ListNode(0,head);
// 设置current指针,current指向head
ListNode* current = dummyHead;
while(current->next != nullptr && current->next->next != nullptr) {
ListNode* tmp = current->next; // 记录临时节点
ListNode* tmp1 = current->next->next->next; // 记录临时节点
current->next = current->next->next; // 步骤一
current->next->next = tmp; // 步骤二
current->next->next->next = tmp1; // 步骤三
current = current->next->next; // cur移动两位,准备下一轮交换
}
return dummyHead->next;
}
};
19.删除链表的倒数第N个结点
先求链表中结点个数,然后返回倒数第N个
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* temp = new ListNode(0,head);//用来求链表长度
ListNode* temp1 = new ListNode(0,head);//作为虚拟头节点最后返回->next
int size = 0;
while(temp->next!=nullptr){
temp->next = temp->next->next;
size++;
}
int result = size - n;
//把temp1存的地址给current
ListNode* current = temp1;
while(result--){
//把current的下一个地址给current
current = current->next;
}
ListNode* tmp = current->next;
current->next = current->next->next;
delete tmp;
return temp1->next;
}
};
还可以用双指针法
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyHead = new ListNode(0);
dummyHead->next = head;
ListNode* slow = dummyHead;
ListNode* fast = dummyHead;
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;
// ListNode *tmp = slow->next; C++释放内存的逻辑
// slow->next = tmp->next;
// delete nth;
return dummyHead->next;
}
};
面试题02.07链表相交
1、求出两个链表的长度
ListNode* curA = headA;
int lenA = 0;
while(curA!=null){
curA = curA->next;
len1++;
}
2、让curA为最长链表的头,lenA为其长度
3、求长度差、然后让两个链表的后端对齐
curA = headA;
while(gap--){
curA = curA->next;
}
4、遍历curA和curB,遇到相同的直接返回
代码如下
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA = headA;
ListNode* curB = headB;
int lenA = 0, lenB = 0;
while (curA != NULL) { // 求链表A的长度
lenA++;
curA = curA->next;
}
while (curB != NULL) { // 求链表B的长度
lenB++;
curB = curB->next;
}
curA = headA;
curB = headB;
// 让curA为最长链表的头,lenA为其长度
if (lenB > lenA) {
swap (lenA, lenB);
swap (curA, curB);
}
// 求长度差
int gap = lenA - lenB;
// 让curA和curB在同一起点上(末尾位置对齐)
while (gap--) {
curA = curA->next;
}
// 遍历curA 和 curB,遇到相同则直接返回
while (curA != NULL) {
if (curA == curB) {
return curA;
}
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
142.环形链表
1、一个fast指针一次移动两个,一个slow指针一次移动一个
2、相遇的点和从头开始移动的点一定会在环形入口处相遇
代码如下
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
//把头指针的地址赋值给slow指针
ListNode* slow = head;
//把头指针的地址赋值给fast指针
ListNode* fast = head;
while(fast!=NULL&&fast->next!=NULL){
//slow指针一次走一个
slow = slow -> next;
//fast指针一次走两个
fast = fast -> next -> next;
//如果出现了相同的地址
if(fast == slow){
//把相交的地址赋值给fast指针
ListNode* index1 = fast;
ListNode* index2 = head;
while(index1!=index2){
index1 = index1->next;
index2 = index2->next;
}
return index2;
}
}
return NULL;
}
};