一.删除链表中给定值val的所有结点
建议自己先动手试一试,20分钟做不出来再看答案。
题目链接:203. 移除链表元素 - 力扣(LeetCode)
既然是要删除链表中所有的头节点,那么就必然有遍历这个操作。
由于是单向链表,我们在删除的时候就需要记录删除链表的前一个节点,不然会找不到。
这里我们使用prev作为第一个节点,cur总是作为prev的后一个节点。
ListNode prev=head;
ListNode cur=head.next;
由cur来找到要删除的节点并进行删除操作。
while(cur!=null){
if(cur.val==val){
prev.next = cur.next;//前一个节点指向要删除节点的下一个,以此达到删除的目的。
}else{
prev=cur;//如果cur的值不等于要删除的值,就让prev向后走一步。
}
cur = cur.next;//cur向后走一步。
}
但是我们会发现一种情况,cur指向的都是prev的下一位,prev是从头节点开始的。
也就是说,如果头节点的值等于要删除的值,那么这么写会删不干净(就剩头节点)。
那么我们来做个判断:
if(head.val==val){
head = head.next;
}
完成之后将它们结合起来,就是这道题的所有代码:
class Solution {
public ListNode removeElements(ListNode head, int val) {
if(head==null){
return null;
}
ListNode prev = head;
ListNode cur = head.next;
while(cur!=null){
if(cur.val==val){
prev.next = cur.next;
}else{
prev=cur;
}
cur = cur.next;
}
if(head.val==val){
head = head.next;
}
return head;
}
}
返回删除后链表的头节点。
二.反转链表
建议自己先动手试一试,20分钟做不出来再看答案。
既然要反转,也就是越后的越元素反转之后越靠前。
那么是不是会想到模拟实现链表的其中一种操作:头插法。
思路是先将头节点变为尾节点然后头节点之后的节点都依次头插进来。
在那之前我们应该保持严谨,看看一开始给的头节点是否为空。
综上:
class Solution {
public ListNode reverseList(ListNode head) {
if(head==null){
return head;
}
ListNode cur = head.next;
head.next=null;
while(cur!=null){
ListNode curN=cur.next;
cur.next=head;
head=cur;
cur=curN;
}
return head;
}
}
三.链表的中间节点
建议自己先动手试一试,20分钟做不出来再看答案。
题目链接:876. 链表的中间结点 - 力扣(LeetCode)
这道题我们需要用到快慢指针的方法。
定义一个fast和slow分别从head出发,fast每次走2步,slow每次走一步。
等到fast走到最后的话,slow所在的节点就是中间节点
想一下为什么会这样?
打一个比方:
跑一圈操场,你和另一个人同时跑,另一个人的速度是你的2倍。
那么他到终点时,你是不是正好在操场终点的一半路程。
class Solution {
public ListNode middleNode(ListNode head) {
if(head==null){
return head;
}
ListNode fast = head;
ListNode slow = head;
while(fast!=null && fast.next!=null){
fast = fast.next.next;
slow = slow.next;
}
return slow;
}
}
以上代码相信大家理解之后都能写出来。
但是fast!=null && fast.next!=null这个可能不太理解,这是因为我们要分2种情况。
一种是节点个数为偶数的:
我们会发现当slow走到0x90的时候,fast已经走到null的位置了。这时如果在走下去就会报错。
一种时节点个数为奇数的情况下:
我们会发现当slow走到0x90的时候,fast已经走到0x65的位置了。这时如果slow走一步,fast走一
步,到这里还没事,但此时fas是null,它还有一步没有走,此时再走剩下的那一步就会报错。
如果你完全理解这些题,那么你绝对会收获不小,自己动手试试吧。