单链表设计LC.707

LeetCode链接

设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的

在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val  的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点

如下图所示:从题目中我们可以条件每个节点的索引是[0 , size -1],以单链表为例进行设计。

 【第一步】:我们设计一个模板,引入size变量记录链表长度,引入虚拟头节点方便进行插入删除索引等操作。

class MyLinkedList {
    // 设置 链表长度
    int size;
    // 设置虚拟头结点
    ListNode dummy;
    // 构造器
    public MyLinkedList() {
        size = 0;
        dummy = new ListNode(0);
    }

    /**
     * 获取链表中第 index 个节点的值,如果索引无效,则返回 -1
     * @param index
     * @return
     */
    public int get(int index) {

    }

    /**
     * 插入头节点
     * @param val
     */
    public void addAtHead(int val) {
        addAtIndex(0,val);
    }

    /**
     * 插入尾节点
     * @param val
     */
    public void addAtTail(int val) {
        addAtIndex(size,val);
    }

    /**
     * 指定插入索引
     * @param index
     * @param val
     */
    public void addAtIndex(int index, int val) {

    }

    /**
     * 删除指定索引的节点,如果索引无效,则返回
     * @param index
     */
    public void deleteAtIndex(int index) {

    }

【第二步】编写get函数

        1. 判断索引是否失效,文章开头就已经介绍了索引范围为[0,size - 1];

        2. 如果想得所以处的值,首先要遍历到该位置。

        3. 最后输出

 代码如下:

/**
     * 获取链表中第 index 个节点的值,如果索引无效,则返回 -1
     * @param index
     * @return
     */
    public int get(int index) {
        // 判断索引是否失效
        if (index < 0 || index >= size) {
            return -1;
        }
        ListNode cur = dummy;
        // 循环寻找到节点
        for (int i = 0; i <= index; i++) {
            cur = cur.next;
        }
        return cur.val;
    }

第三步编写插入函数

插头和插尾函数,可以依赖于addAtIndex。

    // 插头函数
    public void addAtHead(int val) {
        addAtIndex(0,val);
    }
    // 插尾函数
    public void addAtTail(int val) {
        addAtIndex(size,val);
    }
  •  当索引index <= 0 时 插入到链表的头部
  • 当index超过size 需要直接返回
  • index = size 需要插入尾部
  • 其他情况需要找到插入位置然后进行插入

注意:插入的顺序按照图中的1->2->3->

/**
     * 指定插入索引
     * @param index
     * @param val
     */
    public void addAtIndex(int index, int val) {
        // 添加到头部
        if (index <= 0) {
            ListNode newNode = new ListNode(val);
            newNode.next = dummy.next;
            dummy.next = newNode;
            size++;
            return;
        }
        // 超过size 直接返回
        if (index > size) {
            return;
        }

        ListNode newNode = new ListNode(val);
        ListNode pre = dummy;
        for (int i = 0; i < index; i++) {
            pre = pre.next;
        }
        newNode.next = pre.next;
        pre.next = newNode;
        size++;
    }

【第四步】编写删除函数

参考 之前写的文章 一文读懂移除链表元素_abc123mma的博客-CSDN博客

代码

package link;

class MyLinkedList {
    // 设置 链表长度
    int size;
    // 设置虚拟头结点
    ListNode dummy;
    // 构造器
    public MyLinkedList() {
        size = 0;
        dummy = new ListNode(0);
    }

    /**
     * 获取链表中第 index 个节点的值,如果索引无效,则返回 -1
     * @param index
     * @return
     */
    public int get(int index) {
        // 判断索引是否失效
        if (index < 0 || index >= size) {
            return -1;
        }
        ListNode cur = dummy;
        // 寻找到前驱节点
        for (int i = 0; i <= index; i++) {
            cur = cur.next;
        }
        return cur.val;
    }


    /**
     * 插入头节点
     * @param val
     */
    public void addAtHead(int val) {
        addAtIndex(0,val);
    }

    /**
     * 插入尾节点
     * @param val
     */
    public void addAtTail(int val) {
        addAtIndex(size,val);
    }

    /**
     * 指定插入索引
     * @param index
     * @param val
     */
    public void addAtIndex(int index, int val) {
        // 添加到头部
        if (index <= 0) {
            ListNode newNode = new ListNode(val);
            newNode.next = dummy.next;
            dummy.next = newNode;
            size++;
            return;
        }
        // 超过size 直接返回
        if (index > size) {
            return;
        }

        ListNode newNode = new ListNode(val);
        ListNode pre = dummy;
        for (int i = 0; i < index; i++) {
            pre = pre.next;
        }
        newNode.next = pre.next;
        pre.next = newNode;
        size++;
    }

    /**
     * 删除指定索引的节点,如果索引无效,则返回
     * @param index
     */
    public void deleteAtIndex(int index) {
        if (index < 0 || index >= size) {
            return;
        }
        ListNode pre = dummy;
        for (int i = 0; i < index; i++) {
            pre = pre.next;
        }
        pre.next = pre.next.next;
        size--;
    }


    public static void main(String[] args) {
        MyLinkedList linkedList = new MyLinkedList();
        linkedList.addAtHead(1);
        // 此时长度为1
        System.out.println(linkedList.size);
        linkedList.addAtTail(3);
        // 此时长度为2
        System.out.println(linkedList.size);
        linkedList.addAtIndex(1,2);   //链表变为1-> 2-> 3
        // 此时长度为2
        System.out.println(linkedList.size);
        int i = linkedList.get(1);
        // 返回2
        System.out.println(i);
        linkedList.deleteAtIndex(1);  //现在链表是1-> 3
        //返回3
        System.out.println(linkedList.get(1));
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

兜兜转转m

一毛钱助力博主实现愿望

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值