设计链表

设计链表


今天学习了leetcode的链表卡片,其中涉及到了707题 设计链表
题目要求:
设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性: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 个节点。

示例:

MyLinkedList linkedList = new MyLinkedList();
linkedList.addAtHead(1);
linkedList.addAtTail(3);
linkedList.addAtIndex(1,2); //链表变为1-> 2-> 3
linkedList.get(1); //返回2
linkedList.deleteAtIndex(1); //现在链表是1-> 3
linkedList.get(1); //返回3

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/design-linked-list
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

从题目要求中我们需要实现5个方法,即get(index),addAtHead(val),addAtTail(val),addAtIndex(index,val),deleteAtIndex(index).
从addAtHead,addAtTail这两个方法,我们可以得出在定义的链表中定义一个Head,一个Tail属性会比较方便。我这边采取的是一个单链表的实现方式,下面可以定义下MyLinkedList的属性
其中singleNode是定义的一个内部单链表类,有两个属性val,和next

class MyLinkedList {
    public SingleNode head;
    public SingleNode tail;
    //为了方便管理链表长度,便于在进行addAtTail和addAtIndex判断是否越界
    public int listIndex;
    class SingleNode {
        public int val;
        public SingleNode next;

        SingleNode(int val){
            this.val = val;
        }
    }
}

根据示例,首先第一步MyLinkedList linkedList = new MyLinkedList();那么我们就可以写我们的默认构造方法(无参)
在构造函数里面我们定义一个节点让值为-99,并且让头尾节点都指向这个节点,链表长度为0,因为是无参的所以实际上是没有实际的节点。

 public MyLinkedList() {
        SingleNode node = new SingleNode(-99);
        this.head = node;
        this.tail = node;
        this.listIndex = 0;
    }

第二步:linkedList.addAtHead(1);
在添加头节点的时候需要判断当前链表长度是否为0,因为为0的时候添加头节点,同时尾节点也是头节点,并且listIndex需要自增。

 public void addAtHead(int val) {
        SingleNode node = new SingleNode(val);
        if(listIndex == 0){
            head = node;
            tail = node;
        }else{
            node.next = head;
            head = node;
        }
        listIndex ++;
    }

第三步:linkedList.addAtTail(3);
在添加尾节点的时候,也需要判断链表长度是否为0,因为当长度为0的时候新增尾节点头节点也是尾节点。
并且listIndex需要自增。

public void addAtTail(int val) {
        SingleNode node = new SingleNode(val);
        if(listIndex == 0){
            head = node;
        }else{
            tail.next = node;
        }
        tail = node;
        listIndex ++;
    }

第四步:linkedList.addAtIndex(1,2); //链表变为1-> 2-> 3
在往index新增节点的时候,需要判断临界值,如果新增的index都大于链表长度则跳过,如果跟链表长度相等直接调用addAtTail方法,如果index<=0则直接在头节点添加,因为在addAtTail和AddAtHead方法里面都对链表长度自增,因此在这里不需要添加。进入第四个分支,首先将head对象赋给临时temp对象(防止将head的值打乱,导致head指向的并不是真正的头节点),然后遍历到index-1节点,将新增节点放到index-1的next节点,原Index-1的next节点放到新增节点的next节点就完成了节点的获取。

public void addAtIndex(int index, int val) {
        if(index > listIndex){
        }else if(index == listIndex){
            addAtTail(val);
        }else if(index<=0){
            addAtHead(val);
        }else {
            SingleNode temp = head;
            for (int i =1 ;i<index;i++){
                if(temp.next != null){
                    temp = temp.next;
                }
            }

            SingleNode nextTemp = temp.next;
            SingleNode node = new SingleNode(val);
            temp.next = node;
            node.next = nextTemp;
            listIndex ++;
        }
    }

第五步:linkedList.get(1); //返回2
根据listIndex长度判断是否为0判断是否为有效链表,如果为0则不为有效链表则直接返回-1,如果index==0直接返回头节点值,因为是单向链表所以需要遍历到index节点返回值。

public int get(int index) {
        if(listIndex == 0){
            return -1;
        }else {
            if(index== 0){
                return head.val;
            }
            SingleNode temp = head;
            for (int i =1 ;i<=index;i++){
                if(temp.next != null){
                    temp = temp.next;
                }else {
                    return -1;
                }
            }
            return temp.val;
        }
    }

第六步:linkedList.deleteAtIndex(1); //现在链表是1-> 3
如果index是0直接head为head.next,index在0到listIndex就直接遍历到index-1,将index-1的next换成index-1 next的next,同时需要判断去除后是否为尾节点。

 public void deleteAtIndex(int index) {
        if(index == 0){
            head = head.next;
        }else if(index>0 && index<listIndex){
            SingleNode temp = head;
            for (int i =1 ;i<index;i++){
                if(temp.next != null){
                    temp = temp.next;
                }
            }
            SingleNode nextTemp = temp.next.next;
            temp.next = nextTemp;
            if(index == listIndex-1){
                tail = temp;
            }
            listIndex --;
        }
    }

最后代码如下:

class MyLinkedList {
    public SingleNode head;
    public SingleNode tail;
    public int listIndex;
    class SingleNode {
        public int val;
        public SingleNode next;

        SingleNode(int val){
            this.val = val;
        }
    }
    /** Initialize your data structure here. */
    public MyLinkedList() {
        SingleNode node = new SingleNode(-99);
        this.head = node;
        this.tail = node;
        this.listIndex = 0;
    }

    /** Get the value of the index-th node in the linked list. If the index is invalid, return -1. */
    public int get(int index) {
        if(listIndex == 0){
            return -1;
        }else {
            if(index == 0){
                return head.val;
            }
            SingleNode temp = head;
            for (int i =1 ;i<=index;i++){
                if(temp.next != null){
                    temp = temp.next;
                }else {
                    return -1;
                }
            }
            return temp.val;
        }
    }

    /** Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list. */
    public void addAtHead(int val) {
        SingleNode node = new SingleNode(val);
        if(listIndex == 0){
            head = node;
            tail = node;
            listIndex ++;
        }else{
            listIndex ++;
            node.next = head;
            head = node;
        }
    }

    /** Append a node of value val to the last element of the linked list. */
    public void addAtTail(int val) {
        SingleNode node = new SingleNode(val);
        if(listIndex == 0){
            head = node;
        }else{
            tail.next = node;
        }
        tail = node;
        listIndex ++;
    }


    /** Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted. */
    public void addAtIndex(int index, int val) {
        if(index > listIndex){

        }else if(index == listIndex){
            addAtTail(val);
        }else if(index<=0){
            addAtHead(val);
        }else {
            SingleNode temp = head;
            for (int i =1 ;i<index;i++){
                if(temp.next != null){
                    temp = temp.next;
                }
            }

            SingleNode nextTemp = temp.next;
            SingleNode node = new SingleNode(val);
            temp.next = node;
            node.next = nextTemp;
            listIndex ++;
        }
    }

    /** Delete the index-th node in the linked list, if the index is valid. */
    public void deleteAtIndex(int index) {
        if(index == 0){
            head = head.next;
        }else if(index>0 && index<listIndex){
            SingleNode temp = head;
            for (int i =1 ;i<index;i++){
                if(temp.next != null){
                    temp = temp.next;
                }
            }
            SingleNode nextTemp = temp.next.next;
            temp.next = nextTemp;
            if(index == listIndex-1){
                tail = temp;
            }
            listIndex --;
        }
    }
}

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList obj = new MyLinkedList();
 * int param_1 = obj.get(index);
 * obj.addAtHead(val);
 * obj.addAtTail(val);
 * obj.addAtIndex(index,val);
 * obj.deleteAtIndex(index);
 */
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值