目录
- 前言
- 移除链表元素
- 思路分析
- 代码实现
- 链表的中间节点
- 思路分析
- 代码实现
- 反转链表
- 思路分析
- 代码实现
- 链表分割
- 思路分析
- 代码实现
- 合并两个有序链表
- 思路分析
- 代码实现
前言
本篇文章将对部分单链表的OJ题进行讲解
移除链表元素
我们先来看题
思路分析
我们可以采用双指针的方法来解决这个问题,我们用cur指针来遍历链表,找到待删除的元素,并用一个prev指针来保存上一个节点,使该结点的next指向cur结点的next(即待删除元素下一个节点的地址),如果没找到,就将prev指向cur,cur指向cur->next进行迭代。
注意,我们还要考虑第一个节点的val就是待删除元素的情况,这时候的头节点就应该指向下一个节点。
代码实现
代码的实现如下
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val){
struct ListNode*prev=NULL,*cur=head;
while(cur)
{
if(cur->val==val)
{
if(cur==head)
{
head=cur->next;
cur=head;
}
else
{
prev->next=cur->next;
free(cur);
cur=prev->next;
}
}
else
{
prev=cur;
cur=cur->next;
}
}
return head;
}
链表的中间节点
先来看题目描述
思路分析
我们常规的思路是先用cur遍历一遍链表,并保存其长度,然后再遍历长度的一半次,返回最后的节点位置,这个方法可行,但是需要遍历两次链表,有没有方法能只遍历一遍链表就能找出中间节点呢?
当然可以,这里采用的就是快慢指针的方法,慢指针每次走一步,快指针每次走两步,当快指针的下一个节点为空时停止遍历,此时慢指针指向的就是中间节点。
代码实现
代码实现如下
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* middleNode(struct ListNode* head){
struct ListNode* slow=head;
struct ListNode* fast=head;
while(fast->next)
{
slow=slow->next;
fast=fast->next->next;
if(fast==NULL)
break;
}
return slow;
}
反转链表
思路分析
这道题的思路和我们以前做过的<font color=orange.数组元素逆置十分相像,我们知道,要想交换两个位置的值,需要一个中间变量才能实现,所以本题我们也创建一个新的节点来临时保存其中的一个节点,防止出现找不到节点的情况,然后再将节点尾插的即可
代码实现
代码实现如下
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head){
struct ListNode* cur=head;
struct ListNode* pre=NULL;
while(cur)
{
struct ListNode* tmp=cur->next;
cur->next=pre;
pre=cur;
cur=tmp;
}
return pre;
}
链表分割
先来看题目描述
思路分析
1,我们令cur=pHead
2,让cur遍历链表,再开辟两个新结点lessHead和greaterHead,把链表分为两部分,第一部分是小于x的结点放在lessHead->next里,大于x的结点放在greaterHead->next里
3,当cur走到NULL时,让lessTail->next=greaterHead->next,这样就把两个链表按照原来的相对顺序连接起来
4,返回lessHead->next.
代码实现
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
ListNode* partition(ListNode* pHead, int x) {
// write code here
struct ListNode* greatHead, *greattail, *lessHead, *lesstail, *cur;
greatHead = greattail = (struct ListNode*)malloc(sizeof(struct ListNode));
lessHead = lesstail = (struct ListNode*)malloc(sizeof(struct ListNode));
cur = pHead;
while(cur)
{
if(cur->val < x)
{
lesstail->next = cur;
lesstail = cur;
cur = cur->next;
}
else
{
greattail->next = cur;
greattail = cur;
cur = cur->next;
}
}
lesstail->next = greatHead->next;
greattail->next = NULL;
return lessHead->next;
}
};
合并两个有序链表
还是先来看题目描述
思路分析
- 我们首先考虑其中一个链表为空的情形,这样就只用返回另一个头节点即可。
- 然后我们malloc一个节点pS,作为哨兵位,这样就可以避免区分第一个节点是否为空的问题,然后分别遍历list1和list2,用temp指针来接收节点并往后走。
- 当list1或list2有一个为空时停止遍历,然后判断另一个链表是否为空,若不为空,则将temp->next指向不为空的链表的头结点进行链接。
- 最后返回pS->next.
代码实现
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2){
if(list1==NULL) {
return list2;
} else if(list2==NULL) {
return list1;
}
struct ListNode* pS=(struct ListNode*)malloc(sizeof(struct ListNode));
struct ListNode* temp=pS;
while(list1!=NULL && list2!=NULL) {
if(list1->val<=list2->val) {
temp->next=list1;
list1=list1->next;
} else {
temp->next=list2;
list2=list2->next;
}
temp=temp->next;
}
if(list1!=NULL) {
temp->next=list1;
}
if(list2!=NULL) {
temp->next=list2;
}
return pS->next;
}
以上就是本篇文章的全部内容,如有出入,欢迎指正。