题目来自力扣官网: https://leetcode-cn.com/problems/remove-linked-list-elements/
删除链表中等于给定值 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; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
}
}
链表一直理解的不好,没有什么好的方法,硬着头皮写:
肯定是从head开始遍历,判断当前节点n是不是==val,如果等于,就跳过n,让n的前一个节点指向n的后一个节点。
但是如果n是head的时候,没有前一个节点,可以造一个链表头pre指向head,最终返回pre.next。
从pre开始遍历,每次判断当前节点的下一个节点是不是==val,等于就跳过当前节点,不等于就向后移动pre。
为什么需要一个游标呢?一开始我没有想到可以用游标,就是直接操作pre,但是最终是要返回pre.next,
要是pre往后移动了,就没法返回了。返回head也是不行的,有可能pre不指向head了已经,可能跳过了head!所以,搞一个游标(还是应该叫做指针?我理解其实就是一个变量,把pre节点赋值给变量),
然后操作这个游标,pre节点还是在那里没动。
代码如下:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
//记得写边界条件
if(head==null){
return null;
}
//这一段用不用写?
if(head.next==null){
if(head.val==val){
return null;
}else{
return head;
}
}
ListNode pre=new ListNode(0);
pre.next=head;
ListNode p=pre;
while(p.next!=null){
if(p.next.val==val){
//跳过一个
p.next=p.next.next;
}else{
//移动游标p
p=p.next;
}
}
return pre.next;
}
}
再上一个第一次写的代码吧:
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head==null){
return null;
}
if(head.next==null){
if(head.val==val){
return null;
}else{
return head;
}
}
//逻辑是什么:需不需要拼一个链表头?
//假如不拼,判断当前节点是否为空,但是如果head=val怎么办
ListNode n=new ListNode(0);
n.next=head;
//这儿为什么不报错?为什么可以这么写?————这是把n这个节点给了pre,那么pre是一个节点?还是一个游标?
ListNode pre=n;
//ListNode cur=n.next;
//循环
while(pre.next!=null){
if(pre.next.val==val){
if(pre.next.next!=null){
pre.next=pre.next.next;
}else{
pre.next=null;
}
}else{
//这个是把pre往后移动了,还是修改了指针————节点间的指针没有动,但是pre是下一个节点了,是移动游标的操作。
pre=pre.next;
}
}
//这里返回head也不对(可能n不指向head了,返回head就不对了),返回n.next也不对(n.next可能不是head了)
//重要的是要改变head的指针,而且必须返回head这个节点————再搞一个游标pre,然后每次都操作pre。这样n.next就没变,就是head
return n.next;
}
}
实际应该是比较简单的一个问题,这道题做完了以后终于有点理解链表的操作了。再遇到链表的题目可以先把思路想清楚,然后就是写!像是一个把思路翻译成代码的过程,所以必须要熟练。