例1:反转链表
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
解:这道题有递归和迭代两种反转链表的方式。
如果是迭代的话,我们需要使用的是三指针法。首先保证链表不为空,然后创建三个指针(n1、n2、n3),开始时将n1赋值为NULL,n2赋值为head,n3赋值为head->next。 随后进行链表遍历,先让n2->next = n1,然后n1 = n2、n2=n3、当n3!= NULL时,n3也向后移动一个节点,即n3 = n3->next。在循环结束后,n1就是我们新的头结点。
cpp
struct ListNode* reverseList(struct ListNode* head)
{
if(head == NULL)
{
return head;
}
else
{
//三指针法
struct ListNode*n1;
struct ListNode*n2;
struct ListNode*n3;
n1 = NULL;
n2 = head;
n3 = head->next;
//
while(n2)//n2 = NILL时退出循环
{
n2->next = n1;
n1 = n2;
n2 = n3;
if(n2)
{
n3 = n2->next;
}
}
return n1;//返回新的头节点
}
}
如果是递归法的话,我们首先要判断链表的头结点和其下一个节点是否为空,如果为空就不需要反转,直接返回头指针;如果不为空,我们就再次调用本函数,但是参数变成了head->next。随后我们将当前节点的下一个节点的指针指向当前节点,然后将当前节点的指针置为空指针。代码如下:
cpp
// 递归反转链表函数
struct ListNode* reverseList(struct ListNode* head)
{
if (head == NULL || head->next == NULL)
{
return head;
}
// 递归调用反转链表的函数
struct ListNode* new_head = reverseList(head->next);
// 将当前节点的下一个节点的指针指向当前节点,然后将当前节点的指针指向空
head->next->next = head;
head->next = NULL;
return new_head;
}
例2:移除链表元素
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val == val
的节点,并返回 新的头节点 。
提示:
- 列表中的节点数目在范围
[0, 10^4]
内 1 <= Node.val <= 50
0 <= val <= 50
解:这道题你可以选择删除链表中的元素,但我个人认为创建新链表是更简单的方法。
首先我们创建好新的头指针(newhead)和尾指针(newtail)并赋值为NULL,考虑原链表是否为空是必不可少的一步,然后我们就要开始尾插节点了。我们创建一个pcur的临时变量来代替头指针进行遍历链表的操作。当pcur->val不等于val时,我们就尾插代码,这里尾插代码分为空链表的尾插,和非空链表的尾插,空链表的尾插就是newhead=NULL时,我们将newhead和newtail都赋值为第一个不为val的节点,成为非空链表之后,我们就进行简单的尾插就可以了。在循环结束后我们要记得把newtail->next置为空。代码如下:
cpp
struct ListNode* removeElements(struct ListNode* head, int val)
{
struct ListNode* newhead = NULL;
struct ListNode* newtail = NULL;
//空链表
if(head == NULL)
{
return NULL;
}
//非空链表
struct ListNode* pcur = head;
while(pcur)
{
if(pcur->val != val)
{
if(newhead == NULL)
{
newhead = newtail = pcur;
}
else
{
newtail->next = pcur;
newtail = newtail->next;
}
}
pcur = pcur->next;
}
if(newtail)
newtail->next = NULL;
return newhead;
}
例3:链表的中间节点
给你单链表的头结点 head
,请你找出并返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。
提示:
- 链表的结点数范围是
[1, 100]
1 <= Node.val <= 100
解:
这道题我推荐使用快慢指针来做,快和慢只是形容词。我们创建两个指针(slow和fast),将两个指针都赋值为头指针head,然后进行循环,slow一次前进一个节点,fast一次前进两个节点,当fast或者fast->next为空指针时,循环结束,而slow指向的节点就是中间节点。
代码演示:
cpp
struct ListNode* middleNode(struct ListNode* head)
{
//快慢指针
struct ListNode* slow,*fast;
slow = head,fast = head;
//慢指针走一步,快指针走两步,fast到头就停止循环
while(fast && fast->next)
{
slow = slow->next;
fast = fast->next->next;
}
return slow;
}