0
点赞
收藏
分享

微信扫一扫

707. 设计链表(中等 链表)

小时候是个乖乖 2022-01-05 阅读 115

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

提示:

所有val值都在 [1, 1000] 之内。
操作次数将在 [1, 1000] 之内。
请不要使用内置的 LinkedList 库。

分析&题解

分析

学的时候感觉蛮简单的,自己写下来出了好多bug。。
主要出现问题的地方:
1.怎么定义节点,以及节点包含的内容
2.增删查改的过程中,size的变化,以及区间的开闭
双向链表在单向链表的基础上稍微修改即可,这道题没有体现双向链表的优点。

题解(Java)

单链表:

	//单链表
    //先定义节点,节点要带有指针next和内容val
    public class ListNode {
        int val;
        ListNode next;

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

    //构造链表的方法
    class MyLinkedList {
        //定义链表长度
        int size;
        //定义空的头节点
        ListNode head;

        public MyLinkedList() {
            //设置链表初始值
            size = 0;
            head = new ListNode(0);
        }

        public int get(int index) {
            //定义辅助节点遍历链表(因为头节点是固定的,不能动)
            ListNode temp = head;
            if (index >= 0 && index < size) {
                //遍历寻找索引index的节点位置
                for (int i = 0; i <= index; i++) {
                    temp = temp.next;
                }
                //返回该位置节点的值
                return temp.val;
            } else {
                return -1;
            }
        }

        public void addAtHead(int val) {
            //创建值为val的新节点
            ListNode newNode = new ListNode(val);
            ListNode temp = head;
            //注意要先让新节点指向头节点的下一节点,再让头节点指向新节点
            newNode.next = temp.next;
            temp.next = newNode;
            size++;
        }

        public void addAtTail(int val) {
            ListNode newNode = new ListNode(val);
            ListNode temp = head;
            //遍历找到链表尾部
            while (temp.next != null) {
                temp = temp.next;
            }
            temp.next = newNode;
            size++;
        }

        public void addAtIndex(int index, int val) {
            ListNode newNode = new ListNode(val);
            ListNode temp = head;
            //因为index=size时也要放入节点,所以右区间是闭区间
            if (index >= 0 && index <= size) {
                //遍历寻找索引index的前一节点位置,因为要考虑index=size
                for (int i = 0; i < index; i++) {
                    temp = temp.next;
                }
                //判断是否index=size
                if (temp.next != null) {
                    newNode.next = temp.next;
                }
                temp.next = newNode;
                size++;
            }
        }

        public void deleteAtIndex(int index) {
            ListNode temp = head;
            if (index >= 0 && index < size) {
                for (int i = 0; i < index; i++) {
                    temp = temp.next;
                }
                //删除节点的方法
                temp.next = temp.next.next;
                size--;
            }
        }
    }
    /**
	 * 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);
	 */

双向链表:

//双链表
//先定义节点,节点要带有指针next、pre和内容val
public class ListNode {
    int val;
    ListNode next;
    ListNode pre;
    ListNode(int val) {
        this.val = val;
    }
}

//构造链表的方法
class MyLinkedList {
    //定义链表长度
    int size;
    //定义空的头节点
    ListNode head;

    public MyLinkedList() {
        //设置链表初始值
        size = 0;
        head = new ListNode(0);
    }

    public int get(int index) {
        //定义辅助节点遍历链表(因为头节点是固定的,不能动)
        ListNode temp = head;
        if (index >= 0 && index < size) {
            //遍历寻找索引index的节点位置
            for (int i = 0; i <= index; i++) {
                temp = temp.next;
            }
            //返回该位置节点的值
            return temp.val;
        } else {
            return -1;
        }
    }

    public void addAtHead(int val) {
        //创建值为val的新节点
        ListNode newNode = new ListNode(val);
        ListNode temp = head;
        //注意要先让新节点指向头节点的下一节点,再让头节点指向新节点
        if (temp.next != null){
            temp.next.pre = newNode;
            newNode.pre = temp;
        }
        newNode.next = temp.next;
        temp.next = newNode;
        size++;
    }

    public void addAtTail(int val) {
        ListNode newNode = new ListNode(val);
        ListNode temp = head;
        //遍历找到链表尾部
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = newNode;
        newNode.pre = temp;
        size++;
    }

    public void addAtIndex(int index, int val) {
        ListNode newNode = new ListNode(val);
        ListNode temp = head;
        //因为index=size时也要放入节点,所以右区间是闭区间
        if (index >= 0 && index <= size) {
            //遍历寻找索引index的前一节点位置,因为要考虑index=size
            for (int i = 0; i < index; i++) {
                temp = temp.next;
            }
            //判断是否index=size
            if (temp.next != null) {
                temp.next.pre = newNode;
                newNode.next = temp.next;
            }
            temp.next = newNode;
            newNode.pre = temp;
            size++;
        }
    }

    public void deleteAtIndex(int index) {
        ListNode temp = head;
        if (index >= 0 && index < size) {
            //注意这里跟单链表不一样(也可以一样),这里用自我删除
            for (int i = 0; i <= index; i++) {
                temp = temp.next;
            }
            //删除节点
            if (temp.next != null){
                temp.next.pre = temp.pre;
            }
            temp.pre.next = temp.next;
            size--;
        }
    }
}

/**
 * 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 条评论