LeetCode题目描述:移除链表元素
删除链表中等于给定值 val 的所有节点。
示例:
输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5
解题思路:首先保证链表不为空(代码3-6行),由于链表首元素未判断(题目给的链表为不带头结点链表),因此第一步先找到到第一个数据不等于val的节点(代码8-24行)。第二步再对链表中的每个节点的数据进行判断,因为要删除节点,所以需要每次判断后继节点数据和val值,如果后继节点需要删除,则遍历指针不后移,若不删除后继指针,则遍历指针继续向后遍历
当然还有操作更简单的创建头指针法解决,具体可以看下一道题的另一种方法实现!
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* removeElements(struct ListNode* head, int val){
if(head==NULL)
{
return NULL;
}
struct ListNode* cur=head;
while(1)
{
if(cur==NULL)//当链表中只有被删元素时,前面删除完之后链表为空
{
return NULL;
}
if(cur->val==val)
{
struct ListNode*tmp=cur;
cur=cur->next;
free(tmp);
}
else
{
break;//cur结点不为空且cur结点的数据与val不等
}
}
head=cur;
for(;cur->next!=NULL;)
{
if(cur->next->val == val)
{
struct ListNode* tmp=cur->next;
cur->next=cur->next->next;
free(tmp);
}
else
{
cur=cur->next;
}
}
return head;
}
图解:
范例 6->6->1->2->6->3->4->5->6
LeetCode题目描述:删除重复节点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。
例如,
链表1->2->3->3->4->4->5
处理后为 1->2->5**
思路分析:本题其实是上一个题的变种。只不过这次的val值是变化的,只要重复该节点,则val=node->val;
首先判断每个节点和后续节点是否重复,若重复就保存该节点的val值,然后不断删除后面和val值相同的节点,直到遇到和val不同的节点,说明删除完毕,接着下次判断。
若不重复就继续向后遍历判断。
这里有一个开始困扰的情况就是如果头结点就是重复节点,那么该如何删除全部重复节点?
这里有两种解决办法:
- 先不断删除头部重复节点,直到找到第一个不重复的节点作为结束时返回的头结点,若在删除过程中遇到NULL说明该链表中所有节点均有重复;然后再对后继节点和后继next节点的next值判断,若val值相同,则按照上面的解题思路删除重复节点即可
- 另一种就是为了统一操作,申请一个新节点作为头结点,直接按照上面的解题思路遍历就Ok了。
这里代码给出来两种方法的代码实现:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
int data=0;
if(pHead==NULL)
{
return NULL;
}
ListNode *cur=pHead;
ListNode*tmp=NULL;
for(;cur!=NULL&&cur->next!=NULL;)//头结点就出现元素重复,先找到第一个不重复的节点
{
if(cur->val==cur->next->val)//节点重复
{
data=cur->val;
while(cur!=NULL&&cur->val==data)
{
//删除cur节点及之后与cur数据重复的节点
tmp=cur;
cur=cur->next;
free(tmp);
}
if(cur==NULL)
{
return NULL;
}
}
else
{
break;//cur和cur->next的数据不重复,说明cur节点为第一个不重复节点
}
}
pHead=cur;
for(;cur!=NULL&&cur->next!=NULL&&cur->next->next!=NULL;)
{
if(cur->next->val==cur->next->next->val)//判断cur的后继节点是否为重复节点
{
data=cur->next->val;
while(cur->next!=NULL && cur->next->val==data)
{
//删除cur之后和data相同的节点
tmp=cur->next;
cur->next=cur->next->next;
free(tmp);
}
}
else
{
cur=cur->next;
}
}
return pHead;
}
};
创建头结点解法:
/*
struct ListNode {
int val;
struct ListNode *next;
ListNode(int x) :
val(x), next(NULL) {
}
};
*/
class Solution {
public:
ListNode* deleteDuplication(ListNode* pHead)
{
if(pHead==NULL)
{
return NULL;
}
int data;
ListNode*cur=(ListNode*)malloc(sizeof(ListNode));//创建一个头结点,防止传入的头结点就存在重复的情况
cur->next=pHead;
ListNode*head=cur;//记录头结点,防止cur遍历后丢失头结点
ListNode*tmp=NULL;
while(cur->next!=NULL&&cur->next->next!=NULL)
{
if(cur->next->val==cur->next->next->val)
//对cru之后的节点进行判断,如果重复,进入内部循环删除和data相同值的节点
{
data=cur->next->val;
while(cur->next!=NULL&&cur->next->val==data)//删除和data数据相同的cur->next
{
tmp=cur->next;
cur->next=cur->next->next;
free(tmp);
tmp=NULL;
}
}
else
{
cur=cur->next;
}
}
pHead=head->next;
free(head);//释放19行创建的新节点
return pHead;
}
};
以创建头结点法为例作以图解:
用例:1->1->1->2->2->3->4->4->5
LeetCode题目描述:反转一个链表
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
解题思路:
采用指针指向掉头的方法迭代实现,需要注意保存每次掉头的新链表头结点和旧链表的头结点,,然后每次需要一个指针记录即将调转指向节点的后继节点
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* reverseList(struct ListNode* head){
if(head==NULL)
{
return;
}
struct ListNode* cur=head->next;
struct ListNode* tmp=head;
tmp->next=NULL;
while(cur!=NULL)
{
struct ListNode*p=cur->next;
cur->next=tmp;
tmp=cur;
cur=p;
}
head=tmp;
return head;
}
图解: