一.移除链表元素
思路1.额外设prev,next两变量存值
先通过遍历链表找到pcur前一个节点prev,再将pcur后一个节点next存起来,再让prev->next = next,这样是一种解决方法。
思路2.创建新链表(实现)
检测pcur->val如果不等于val值,就将新节点插入原节点尾,如果是空链表则直接将头和尾节点都赋值为pcur
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val)
{
ListNode* NewHead;
ListNode* NewTail;
NewHead = NewTail = N ULL;
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(NewHead)//如果新链表不为空
{
NewTail->next = NULL;
}
return NewHead;//如果为空直接返回空即可
}
需要注意的是,如果给的链表就是空链表,则不进while循环,直接返回空即可。
二.反转单链表
思路1.创建新链表
创建新链表,遍历原链表,将原链表的节点拿来头插即可完成
思路2.不创建新链表,创建三个指针(实现)
改变n2的next指针,由指向n3改变至指向n1
再通过赋值操作,将n1,n2,n3向后走,究其本质其实就是改变箭头的指向,代码如下
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head) {
if(head == NULL)
return head;
ListNode* n1 = NULL;
ListNode* n2 = head;
ListNode* n3 = n2->next;
while(n2)
{
n1 = n2->next;
n1 = n2;
n2 = n3;
if(n3)
n3 = n3->next;
}
}
最后注意传入空链表则直接返回,n3遍历到空需要判断,让它不要再往后走了。
三.返回链表的中间节点
1.遍历原链表
定义变量count计节点数,直接返回(count / 2)->next节点,需要遍历多次。
2.快慢指针(实现)
定义两个指针fast,slow.slow一次走一步,fast一次走两步.
节点有奇数个:
fast->next == NULL时,slow节点就是中间节点
节点有偶数个:
fast == NULL时,slow节点就是中间节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast && fast->next)//不能交换位置,fast为空,即证明为偶数节点,fast->next为空,即证明为奇数节点
{
slow = slow->next;
fast = fast->next->next;
}
//此时slow就是指向中间节点的指针
return slow;
}
四.总结
对于链表类题,我们可以使用
创建链表
额外设值存值来避免创建链表
通过多指针来改变链表的指向
一种比较巧妙的方法-----快慢指针
......