一、203.移除链表元素
题目:203. 移除链表元素 - 力扣(LeetCode)
视频:手把手带你学会操作链表 | LeetCode:203.移除链表元素_哔哩哔哩_bilibili
讲解:代码随想录
注意:
针对头结点和非头结点的删除方式是不一样的:
正常节点:要找到该节点的上一节点
头结点:直接把 head 往后移一位
所以就要进行判断,要删除的节点是不是头结点(方法一)
或者,在头结点前设立一个虚拟节点(dummy head)(方法二)
方法一:判断链表删除元素
class Solution {
public ListNode removeElements(ListNode head, int val) {
while (head != null && head.val == val) {
head = head.next;
}
ListNode curr = head;
while (curr != null && curr.next != null) {
if (curr.next.val == val) {
curr.next = curr.next.next;
} else {
curr = curr.next;
}
}
return head;
}
}
要点 1:
判断头结点是否符合的时候,使用 if 就只能判断一次,如果第二个元素也符合条件,就漏删了
所以要用 while ,在头结点不符合条件的时候,才继续往下走
要点 2:
往后查找的时候,要定义一个指针,那么指针的位置指向哪里?
如果是第二位,第二位符合删除条件,找不到上一位的 next 指针。(x)
所以要指向头结点
尝试过程:
class Solution {
public ListNode removeElements(ListNode head, int val) {
while (head != null && head.val == val) {
head = head.next;
}
ListNode curr = head;
while (curr.next != null && curr != null) { //这里有问题!!
if (curr.next.val == val) {
curr.next = curr.next.next;
} else {
curr = curr.next;
}
}
return head;
}
}
报这个错误的原因:
虽然从逻辑上看是想同时确保当前节点 curr
和它的下一个节点 curr.next
都不为 null
,但如果 curr
本身已经是 null
了,再去访问 curr.next
就会直接抛出空指针异常。
正确的做法应该是先判断 curr
是否为 null
,再去判断 curr.next
是否为 null
,像这样修改条件为 while (curr!= null && curr.next!= null)
。
方法二:设置虚拟头结点
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummy = new ListNode();
dummy.next = head;
ListNode curr = dummy;
while(curr != null && curr.next != null){
if(curr.next.val == val){
curr.next = curr.next.next;
} else {
curr = curr.next;
}
}
return dummy.next;
}
}
注意头结点的指针是不能更改的,因为最后要用到头结点返回。
二、707.设计链表
题目:707. 设计链表 - 力扣(LeetCode)
视频:帮你把链表操作学个通透!LeetCode:707.设计链表_哔哩哔哩_bilibili
讲解:代码随想录
利用虚拟头结点方式,对所有结点统一操作。
class MyLinkedList {
class ListNode {
int val;
ListNode next;
ListNode(int val) {
this.val = val;
}
}
private int size;
private ListNode head;
// 初始化
public MyLinkedList() {
this.size = 0;
this.head = new ListNode(0);
}
public int get(int index) {
if (index < 0 || index >= size) {
return -1;
}
ListNode cur = head;
for (int i = 0; i <= index; i++) {
cur = cur.next;
}
return cur.val;
}
public void addAtHead(int val) {
ListNode newNode = new ListNode(val);
newNode.next = head.next;
head.next = newNode;
size++;
}
public void addAtTail(int val) {
ListNode newNode = new ListNode(val);
ListNode cur = head;
while (cur.next != null) {
cur = cur.next;
}
cur.next = newNode;
size++;
}
public void addAtIndex(int index, int val) {
if (index < 0 || index >= size) {
return;
}
ListNode cur = head;
for (int i = 0; i < index; i++) {
cur = cur.next;
}
ListNode newNode = new ListNode(val);
newNode.next = cur.next;
cur.next = newNode;
size++;
}
public void deleteAtIndex(int index) {
if(index < 0 || index >=size){
return;
}
ListNode cur = head;
for(int i=0; i<index; i++){
cur = cur.next;
}
cur.next = cur.next.next;
size--;
}
}
三、206.反转链表
题目:
视频:
讲解: