LeetCode 算法学习记录 链表 707 设计链表

//题中需要我们实现一个链表,并且实现几种链表的常见操作,
//
//获取指定位置的节点
//插入头结点
//插入尾部节点
//插入指定位置节点
//删除指定节点

//易错点在对index的处理上,我们在实现的时候在注意index的合法性,比如index是否小于0 或者大于等于链表长度的时候,还应该注意index出现在循环中时如何确认循环的边界
//难点在对头结点的处理上,因为对头结点进行的操作步骤与普通节点不同,插入与删除操作中,目标为普通节点找到其前驱就可以了,,但是头结点没有前驱节点,所以在插入跟删除时就需要对头结点与普通节点分开操作,这样就增加了操作的复杂性,我们应该找到一个普遍的方法可以同时处理头结点与普通节点就可以了,答案就是创建一个虚拟节点,当做头结点来使用,这用实际的头结点就成了第二的节点,这样我们在操作时就可以一起操作了,头结点的前驱就是刚刚创建的虚拟节点
//解决方法,在链表初始化的时候,初始化一个虚拟节点,但是注意因为节点是虚拟的所以链表长度初始化时要为0
//其中第一个方法实现起来很简单,判断完index合法性后,只需要创建一个临时节点,并把头节点赋值给他,然后向后遍历找到目标节点就可以了


class MyLinkedList {
    // 结点类
    class Node {
        // 结点的值
        int val;
        // 指向下一个结点的指针(java中表现为下一个结点的引用)
        Node next;
        // 初始化 数据域val
        Node(int val) {
            this.val = val;
        }
    }

    // 记录头结点/指针
    Node head;
    // 记录链表的长度(元素的个数) 因为下面要用到,用于判断index的合法性
    int N;

    // 初始化  构造方法
    public MyLinkedList() {
        // 初始化长度
        N = 0;
        // 初始化头结点 这里建立了一个虚拟头结点,这个节点指向头结点,
        // 现在因为没有头结点,所以指向null
        head = new Node(0);
    }

    // 获取指定 索引index 的结点
    public int get(int index) {
        //判断index的合法新
        if (index < 0 || index >= N) {
            return -1;
        }
        //建立一个临时节点来遍历链表找到目标位置的节点
        Node temp = this.head;
        for (int i = 0;i<=index;i++) {
            //不到目标位置,则临时节点向后移动,知道移动到指定位置
            temp = temp.next;
        }
        return temp.val;
    }

    // 头部插入
    public void addAtHead(int val) {
        this.addAtIndex(0,val);
    }

    // 尾部插入
    public void addAtTail(int val) {
        this.addAtIndex(N,val);
    }

    // 任意插入
    public void addAtIndex(int index, int val) {
        //判断index合法性 大于链表长度则直接返回
        if (index > N) {
            return;
        }
        //小于0代表插入到头结点,index改为0
        if (index < 0) {
            index = 0;
        }
        N++;
        Node temp = head;
        //查找要插入节点的前驱
        //注意插入头结点的插入方法与普通节点不同,因为头结点没有前驱,
        //但是虚拟节点指向头结点,也就是说头结点的前驱是虚拟节点
        //所以头结点的插入也可以按照铺头节点的插入方法进行插入,
        //只要找到前驱即可
        for (int i = 0; i < index; i++) {
            temp = temp.next;
        }
        //找到后进行插入操作
        Node node = new Node(val);
        node.next = temp.next;
        temp.next = node;
    }

    // 删除
    public void deleteAtIndex(int index) {
        //判断index合法性 大于链表长度或者小于0则直接返回
        if (index >= N || index < 0) {
            return;
        }
        N--;
        Node temp = head;
        //这里跟上面一样,只要找到要删除位置的前驱指针,
        //因为有虚拟头指针的存在所以实际头指针也有前驱
        for (int i = 0; i < index; i++) {
            temp = temp.next;
        }
        //找到后进行插入操作
        temp.next = temp.next.next;
    }
}

/**
 * MyLinkedList对象将被实例化并这样调用:
 * MyLinkedList obj = new MyLinkedList();
 * int param_1 = obj.get(index);
 * obj.addAtHead(val);
 * obj.addAtTail(val);
 * obj.addAtIndex(index,val);
 * obj.deleteAtIndex(index);
 */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值