1.Leetcode.24 两两交换链表中的结点:
本题较为简单,在题干中可以看到,系统给定的样例存在空链表,因此,为了避免空链表造成的访问错误,本题也采用人为添加哨兵位头结点的方式。例如对于图中给出的链表,在加上哨兵位头结点后,链表的结构可以表示如下:
对于题目中的要求,即交换结点,可以通过下面的动作完成:
(注:完成交换结点的方法有多种,文章暂提供一种)
首先保存第一,二个结点,并且将这两个结点的地址用两个指针变量保存。
在建立号变量后,首先建立第一个结点和第三个结点的练习,即:
然后再建立的联系:
最后建立哨兵位头结点和结点的联系,即:
对于上述的图形稍加整理,即:
在演示了上述过程后,不难看出,如果想要交换两个结点需要在这两个结点中,靠前一个结点的前一个结点最为起始结点开始操作,对于上述链表,如果想要对结点进行操作,则需要将
作为起始结点。
因此,对于循环的判定条件也可以直接得出,对于上述链表,当对结点操作后,下一次进行操作的起始结点的位置在链表中的第
结点。由于在
后不存在结点,因此可以将检测起始结点的下一个结点是否为空作为循环是否结束的判定条件。
但是,这种情况只适用于链表中的结点为偶数个。对于链表中结点为奇数个的情况,例如在上述给出的链表中再添加一个结点,即:
按照上面所说,在交换完结点后,进行下一次交换操作的起始结点应该为链表中的第四个结点。因此,对于链表中结点个数为奇数个的情况,应该检查结点的下下个结点是否为空。
代码如下:
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode* phead = new ListNode(0);
phead->next = head;
ListNode* cur = phead;
while(cur->next != nullptr && cur->next->next != nullptr)
{
ListNode* tmp1 = cur->next->next;
ListNode* tmp2 = cur->next;
tmp2->next = tmp1->next;
tmp1->next = tmp2;
cur->next = tmp1;
cur = cur->next->next;
}
return phead->next;
}
};
2. Leetcode.19 删除链表的倒数第N个结点:
19. 删除链表的倒数第 N 个结点 - 力扣(LeetCode)
题目难度较低,为了删除链表中的倒数第个结点,首先需要找到链表中倒数第
个结点。为了消除空链表对于链表遍历带来的影响,需要人为加上哨兵位头结点。在寻找目标结点时,只需要先定义两个指针变量
,让
先向前走
步,再令
一起向后遍历,直到
为空。具体可以用下面的图片进行表示:
但是这样只是可以找到目标结点,并不能达到删除结点的目的。为了达成删除结点的目的,需要找到目标结点的前一个结点。因此,可以让结点在最开始走
步,即:
再让两个结点一起向后进行遍历,即:
最后在进行删除结点的操作,对于如何删除结点原理过于简单,因此不过多叙述,只给出代码:
class Solution {
public:
ListNode* removeNthFromEnd(ListNode* head, int n) {
ListNode* phead = new ListNode(0);
phead->next = head;
ListNode* fast = phead;
ListNode* slow = phead;
int n1 = n+1;
while(n1--)
{
fast = fast->next;
}
while(fast != nullptr)
{
fast = fast->next;
slow = slow->next;
}
ListNode* tmp = slow->next->next;
slow->next = tmp;
return phead->next;
}
};
3. 面试题.02.07 链表相交:
面试题 02.07. 链表相交 - 力扣(LeetCode)
原理也较简单,首先创建两个用于遍历的指针,遍历一遍两个链表,统计两个链表的长度,然后在创建变量
用于计算两个链表长度的差值。在比较两个链表的长度,让长的链表的头结点先向前遍历
次,最后两个链表一起向后遍历,并且比较此时结点的指针是否相同即可。对应代码如下:
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* curA = headA;
ListNode* curB = headB;
int Asum = 0,Bsum = 0;
while(curA != nullptr)
{
curA = curA->next;
Asum += 1;
}
while(curB != nullptr)
{
curB = curB->next;
Bsum += 1;
}
int span = 0;
span = abs(Asum-Bsum);
if(Asum > Bsum)
{
while(span--)
{
headA = headA->next;
}
}
else
{
while(span--)
{
headB = headB->next;
}
}
while(headA != nullptr)
{
if(headA == headB)
{
return headA;
}
headA = headA->next;
headB = headB->next;
}
return 0;
}
};
4. Leetcode.142 环形链表Ⅱ:
对于本题,难点主要在于对于一个关系式的证明,在之前的文章LeetCode.141,142——环形链表,环形链表Ⅱ-CSDN博客给出了详细的推理以及证明。本处只给出代码:
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* slow = head;
ListNode* fast = head;
while(fast && fast->next)
{
slow = slow->next;
fast = fast ->next->next;
if(slow == fast)
{
ListNode* meet = slow;
while(head != meet)
{
head = head->next;
meet = meet->next;
}
return head;
}
}
return NULL;
}
};