24. 两两交换链表中的节点
思路:定义虚拟头结点,定义两个临时节点,用于中间操作,每次改变三个结点的链接关系,改变完之后,讲cur移动到第三个结点继续循环,当cur后不足两个结点时,停止循环,输出链表。
/**
* 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* dummyhead = new ListNode(0);
dummyhead->next = head;
ListNode* cur = dummyhead;
ListNode* temp1 = new ListNode(0);
ListNode* temp2 = new ListNode(0);
while(cur->next!=NULL&&cur->next->next!=NULL)
{
temp1 = cur->next;
temp2 = cur->next->next->next;
cur->next = cur->next->next;
cur->next->next = temp1;
temp1->next=temp2;
cur = temp1;
}
return dummyhead->next;
}
};
19. 删除链表的倒数第 N 个结点
思路:构建pre和cur两个结点,他们之间的距离为N,这样当cur指向最后一个结点时,pre指向倒数第N个结点的前一个结点,此时可以执行删除操作。
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* dummyhead = new ListNode(0);
dummyhead->next=head;
ListNode* pre = dummyhead;
ListNode* cur = dummyhead;
while(n--)
{
cur = cur->next;
}
while(cur->next!=NULL)
{
pre=pre->next;
cur = cur->next;
}
pre->next = pre->next->next;
return dummyhead->next;
}
};
160. 相交链表
思路:先计算链表A和链表B的长度差h,然后在长的链表中定义cur结点,移动h位,使得两个链表的尾端对其,然后同时开始移动结点,找到结点相同的位置,即相交结点。
/**
* 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) {
//找长度
ListNode * curA = headA;
ListNode * curB = headB;
int sizeA = 0;
int sizeB = 0;
while(curA!=NULL)
{
curA = curA->next;
sizeA++;
}
while(curB!=NULL)
{
curB = curB->next;
sizeB++;
}
curA = headA;
curB = headB;
if(sizeA>=sizeB)
{
int length = sizeA-sizeB;
while(length)
{
curA = curA->next;
length--;
}
while(curA!=NULL)
{
if(curA ==curB)
{
return curA;
}
curA = curA->next;
curB= curB->next;
}
}
else
{
int length = sizeB-sizeA;
while(length)
{
curB = curB->next;
length--;
}
while(curB!=NULL)
{
if(curB ==curA)
{
return curB;
}
curA = curA->next;
curB= curB->next;
}
}
return NULL;
}
};
142.环形链表II
思路:设置快慢结点,快结点每次移动两位,慢结点每次移动一位,移动速度差为1结点,如果有环,快结点先进入环,随后会在环内追上慢结点,追上慢结点时,快结点移动的结点数为x+y+n*(y+z),其中x为进入环前的结点数,y+z为环内结点数,y为慢结点进入环后移动的节点数;慢结点移动的节点数为x+y;满足满足等式2*(x+y) = x+y+n*(y+z); 当n = 1时,x = z;当慢结点与快结点在环内相遇后,头结点与当前位置的结点同时移动,相遇处即为链表进入环的第一个结点。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* slow = head;
ListNode* fast = head;
while (fast!=NULL&&fast->next!=NULL)
{
slow= slow->next;
fast = fast->next->next;
if (slow==fast)
{
ListNode *temp = fast;
ListNode *temp1 = head;
while(temp!=temp1)
{
temp =temp->next;
temp1 = temp1->next;
}
return temp;
}
}
return NULL;
}
};
收获:
这几道题在不久前做过,有一些印象,今天做的比较快,复习了一下链表的知识。
要注意循环的判断,循环停止的边界是什么。