203、 移除链表元素
给你一个链表的头节点 head
和一个整数 val
,请你删除链表中所有满足 Node.val ==
val
的节点,并返回 新的头节点 。
对于删除链表节点的题目,一般是先构造一个虚拟的头节点,让这个虚拟的头节点与原来的
头节点相连,因为我们不知道原来的头节点的数据是不是与要删除的数据相等,因此最好的办法就
是构造一个虚拟头节点,然后利用双指针进行处理;具体代码如下
class Solution {
public:
ListNode* removeElements(ListNode* head, int val) {
struct ListNode *virhead=(struct ListNode *)malloc(sizeof(struct ListNode));
virhead->next=head;
struct ListNode *p=head;
struct ListNode *prev=virhead;
while(p){
if(p->val!=val){ //如果当前的值不是要删除的元素,就让prev移动到现在p所在的位置上,p继续移动
prev=p;
}else{ //表示当前的值是要删除的,就让prev指向p的下一个元素,并且让p向后移动一个
prev->next=p->next;
}
p=p->next;
}
return virhead->next;
}
};
链表的题目无非就是就是改变一下结点的指向,所以我们要时刻关注一下,当前节点的下一
个节点,还有当前节点的上一个节点以及当前节点,但是要注意的是要先判断当前节点是否为空节
点,如果为空节点,后续的操作就不用进行了;
206、 反转链表
给你单链表的头节点 head
,请你反转链表,并返回反转后的链表。
这一题的思路是怎样的呢?我们可以这样想,让1节点指向空,让2节点指向1节点,以此类
推即可,当我们遍历1结点的时候,这时应该先记录1节点的下一个节点,temp=p->next;便于下
一次循环,然后改变1节点的指向,具体代码如下:
class Solution {
public:
ListNode* reverseList(ListNode* head) {
if(!head || !head->next) return head;
struct ListNode *prev=NULL;
struct ListNode *p=head;
struct ListNode *temp;
while(p){
temp=p->next;
p->next=prev;
prev=p;
p=temp;
}
return prev;
}
};
24、 两两交换链表的结点
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改
节点内部的值的情况下完成本题(即,只能进行节点交换)。
本题要求我们只能进行节点的交换,不能修改结点的值,我们首先要构造一个虚拟的头节点
然后开始遍历原链表的第一个节点,也就是虚拟节点的下一个节点,遍历的时候我们必须要知道
当前节点的上一个节点,当前节点的下一个节点绝对不能为空,一旦为空了,就退出循环,具体的
看下面的代码了;
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode *virhead=(ListNode *)malloc(sizeof(struct ListNode));
virhead->next=head;
ListNode *prev=virhead;
ListNode *p=head;
while(p && p->next){ //必须要保证p不是空指针,并且p->next也不是空指针,
ListNode *temp=p->next;
p->next=temp->next; //如果没有上面这个循环条件的话,这里会出现空指针的访问
temp->next=prev->next;
prev->next=temp;
prev=p;
p=p->next;
}
return virhead->next;
}
};
上述代码中最经典的是while循环里面的部分,一开始的时候就说了,链表的题目就是改变
节点的指向,节点指来指去,我们通常采用的是先连后断的思想;