版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhangvalue/article/details/88578027
【题目描述】
删除链表中等于给定值 val 的所有节点。
示例:
输入: 1->2->6->3->4->5->6, val = 6
输出: 1->2->3->4->5
同时给定了固定的结点数据结构
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
考虑使用三种方式来进行删除:
1️⃣直接访问单链表进行删除、
2️⃣使用头结点删除、
3️⃣使用递归删除
方法一、直接访问单链表进行删除。
此时分成分成了三种情况,第一个就是如果第一个结点就是要删除的结点,而因为没有头结点,所以需要一个一个判断第一个结点在其删除之后的情况,当第一个结点不再是待删除的结点的时候,此时可能链表已经为null就不需要后续。如果在链表中间有待删除的结点,此时就是需要使用一个结点prev作为待删除结点的前面一个结点。
class Solution {
public ListNode removeElements(ListNode head, int val) {
//一开始就开始判断头结点是不是为null,如果不为null且其val值就是要删除的结点就删除该结点
while(head!=null&& head.val==val){
ListNode delNode = head;
head=head.next;
//将要删除的节点的next置为null,便于回收
delNode.next=null;
}
//考虑到如果只有一个结点后续就用讨论直接返回null即head
if(head==null){
return head;
}
//此时创建一个prev结点表示要待删除结点的前一个结点
//而且此时的prev肯定不会为null因为前面已经讨论过了 当当前head为null的情况
ListNode prev = head;
//能够执行到此处,说明此事head肯定不是null,因此判断循环条件为next是否为null
//单链表中要删除一个结点一定知道其前面一个结点
while(prev.next!=null){
//判断当前结点的next结点的val是否为要求的val
if(prev.next.val==val){
ListNode delNode = prev.next;
prev.next=delNode.next;
//将要删除的节点的next置为null,便于回收
delNode.next=null;
}else{
prev=prev.next;
}
}
return head;
}
}
方法二、使用链表中的一个头结点的形式。
就不需要在删除的时候单独考虑第一个结点是否为空的情况,此时判断起来就比较容易,因为创建的头结点本身在指向的时候就是要删除结点的前面的结点
class Solution {
public ListNode removeElements(ListNode head, int val) {
//使用头结点的方式 创建一个头结点
ListNode dummynode = new ListNode(-1);
//将头结点的next指向head
dummynode.next = head;
ListNode prev = dummynode;
//循环遍历链表直到最后链表中最后一个结点
while(prev.next!=null){
if(prev.next.val==val){
prev.next=prev.next.next;
}else{
prev=prev.next;
}
}
//最后返回的是头结点指向的第一个结点
return dummynode.next;
}
}
方法三、使用递归调用的过程来进行删除
首先需要将整个单链表看做为由其第一个结点和其后续的结点构成的结构,那么同理,其后续结点也是一个递归的结构。
因为被删除的结点之后构成了还是一个链表的形式。在进行递归的时候,构建一个res结点用来接收删除结点之后的部分,再判断当前的结点中是否同样为符合被删除条件,符合就直接返回res,不符合就拼接起来返回head
class Solution {
public ListNode removeElements(ListNode head, int val) {
//最开始判断如果头结点为null就不需要进行删除,直接返回为null
if(head==null){
return null;
}
//采用递归调用的方法来删除
//将原来的链表看做是一个结点加上后面的部分,
//同时后面的部分也是由一个结点和其后续节点构成
//因为被删除的结点之后构成了还是一个链表的形式
//构建一个res结点用来接收删除结点之后的部分
ListNode res= removeElements(head.next,val);
//因为已经判断删除掉了head的next后续的部分,此时再看看head结点是否符合被删除的条件
//如果符合就直接返回删除返回之后的res
if(head.val==val){
return res;
}else {
//如果head不符合被删除的条件,就把后续没有被删除的结点拼接上返回head
head.next=res;
return head;
}
}
}
上述的递归算法还可以更加精简一些
class Solution {
public ListNode removeElements(ListNode head, int val) {
//最开始判断如果头结点为null就不需要进行删除,直接返回为null
if(head==null){
return null;
}
//采用递归调用的方法来删除
//将原来的链表看做是一个结点加上后面的部分,
//同时后面的部分也是由一个结点和其后续节点构成
//因为被删除的结点之后构成了还是一个链表的形式
//构建一个结点用来接收删除结点之后的部分
head.next= removeElements(head.next,val);
return head.val==val?head.next:head;
}
}