题目一 203. 移除链表元素 - 力扣(LeetCode)
思路
- 链表的定义
* Definition for singly-linked list.
* public class ListNode {
// 属性
* int val;
* ListNode next;
// 构造函数
* ListNode() {}
* ListNode(int val) { this.val = val; }
* ListNode(int val, ListNode next) { this.val = val; this.next = next; }
* }
- 虚拟头节点
ListNode dummy = new ListNode();
dummy.next = head;
设置虚拟头节点,通过dummy.next来操作真正的头节点,统一所有节点的处理逻辑;否则,需要特殊考虑头节点满足条件的情况
- 原链表为空
- 默认先处理特殊情况:若
head = [],则head == null,返回dummy.next - 看逻辑能否合并,若可以,删除特殊情况代码即可
代码
错误解法
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummy = new ListNode(0,head);
ListNode cur = dummy;
while(cur.next != null) {
if(cur.next.val == val) {
cur.next = cur.next.next;
}
cur = cur.next;
}
return dummy.next;
}
}
- 程序报错
cannot read field next because local4 is null - 如果if满足条件,cur.next会更新到下下个,这个时候cur.next可能为null
- 继续执行
cur = cur.next;当前的cur会指向空 正确代码:
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummy = new ListNode(0, head);
ListNode cur = dummy;
while(cur.next != null) {
if(cur.next.val == val){
cur.next = cur.next.next;
}else{
cur = cur.next;
}
}
return dummy.next;
}
}
- 若不满足值相等的条件,则向后移动cur指针;
- 若满足值相等的条件,则更新cur.next,而且不需要向后移动cur指针
所以,代码可以写成:
class Solution {
public ListNode removeElements(ListNode head, int val) {
ListNode dummy = new ListNode(0, head);
ListNode cur = dummy;
while(cur.next != null) {
if(cur.next.val != val){
cur = cur.next;
}else{
cur.next = cur.next.next;
}
}
return dummy.next;
}
}
题目二707. 设计链表 - 力扣(LeetCode)
思路
为了设计链表类,初始化需要定义两个属性,虚拟头节点和size
class MyLinkedList {
int size; // 虚拟头节点
Node dummy;
public MyLinkedList() {
// 初始化
size = 0;
dummy = new Node(0); }
- get(index)
- 进行index有效性验证
- cur指向dummy.next
代码
public int get(int index) {
// INDEX从0开始
if(!(index >= 0 && index < size)) {
return -1;
}
LinkedNode cur = dummy.next;
while(index > 0) {
cur = cur.next;
index--;
}
return cur.val;
}
- addAtHead(val)
public void addAtHead(int val) {
// 插入节点先定义新链表节点
LinkedNode newnode = new LinkedNode(val);
// 注意插入顺序
newnode.next = dummy.next;
dummy.next = newnode;
// 记得改容量
size ++;
}
- addAtTail(int val)
public void addAtTail(int val) {
// 插入节点先定义新链表节点
LinkedNode newnode = new LinkedNode(val);
// 先指向最后一个节点
LinkedNode cur = dummy;
while(cur.next != null){
cur = cur.next;
}
// 修改尾部节点的指向关系
cur.next = newnode;
size++;
}
- addAtIndex(int index, int val)
public void addAtIndex(int index, int val) {
if(index > size) {
return;
}
// 插入节点先定义新链表节点
LinkedNode newnode = new LinkedNode(val);
// 先指向插入位置的前一个
LinkedNode cur = dummy;
while(index > 0){
cur = cur.next;
index--;
}
// 修改节点的指向关系
newnode.next = cur.next;
cur.next = newnode;
size++;
}
- deleteAtIndex(int index)
public void deleteAtIndex(int index) {
// 数据有效性
if(!(index >= 0 && index < size)) {
return;
}
// 先指向删除位置的前一个
LinkedNode cur = dummy;
while(index > 0){
cur = cur.next;
index--;
}
// 修改节点的指向关系
cur.next = cur.next.next;
size--;
}