【数据结构】链表 | 设计链表

656 阅读2分钟

题目一 203. 移除链表元素 - 力扣(LeetCode)

image.png

思路

  1. 链表的定义
 * 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; }
 * }
  1. 虚拟头节点
ListNode dummy = new ListNode();
dummy.next = head;

设置虚拟头节点,通过dummy.next来操作真正的头节点,统一所有节点的处理逻辑;否则,需要特殊考虑头节点满足条件的情况

  1. 原链表为空
  • 默认先处理特殊情况:若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;
    }
}
  1. 程序报错cannot read field next because local4 is null
  2. 如果if满足条件,cur.next会更新到下下个,这个时候cur.next可能为null
  3. 继续执行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;
    }
}
  1. 若不满足值相等的条件,则向后移动cur指针;
  2. 若满足值相等的条件,则更新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)

image.png

思路

为了设计链表类,初始化需要定义两个属性,虚拟头节点和size

class MyLinkedList { 
int size; // 虚拟头节点 
Node dummy; 
public MyLinkedList() { 
// 初始化 
size = 0; 
dummy = new Node(0); }
  1. 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;
    }
  1. addAtHead(val)
    public void addAtHead(int val) {

        // 插入节点先定义新链表节点
        LinkedNode newnode = new LinkedNode(val);
        // 注意插入顺序
        newnode.next = dummy.next;
        dummy.next = newnode;
        // 记得改容量
        size ++;
    }
  1. 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++;
    }
  1. 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++;
    }
  1. 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--;
    }