[路飞]_程序员必刷力扣题: 707. 设计链表

174 阅读3分钟

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 库。

数组两头截取

思路

  • new MyLinkedList: 这里我们生成一个head头结点,在其后保存真正有效的链表,return head节点的next
  • addAtHead:在头节点新增节点,直接操作next指向
  • addAtTail:遍历链表找到尾结点,新增元素
  • get:正常遍历链表,找到第index个值return,末尾return -1 表示没有找到
  • addAtIndex:新增到指定位置,index小于等于0直接新增在头节点,然后比较如果循环到第I个刚好等于index-1,代表当前节点为index的前一个节点,则在当前节点后面插入新节点
  • deleteAtIndex: 删除第index个节点,别那么就是要处理index的前一个节点,所以这里我们i从-1开始,遍历从this.Head开始,省去处理边界的情况。正常遍历找到i===index-1的位置开始删除,让node的next指针指向next.next
var MyLinkedList = function () {
    this.Head = {
        val: 'head',
        next: null
    }
    return this.Head.next
};

/** 
 * @param {number} index
 * @return {number}
 */
MyLinkedList.prototype.get = function (index) {
    if (index < 0) return -1
    var i = 0
    var node = this.Head.next
    while(node){
        if(i===index) return node.val
        node = node.next
        i++
    }
    return -1
};

/** 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtHead = function (val) {
    var newNode = {
        val,
        next:this.Head.next
    }
    this.Head.next = newNode
};

/** 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtTail = function (val) {
    var lastNode = this.lastNode()
    lastNode.next = {
        val,
        next:null
    }
};

MyLinkedList.prototype.lastNode = function (val) {
    var node = this.Head
    while(node){
        if(!node.next) return node
        node = node.next
    }
};

/** 
 * @param {number} index 
 * @param {number} val
 * @return {void}
 */
MyLinkedList.prototype.addAtIndex = function (index, val) {
    if(index<=0) this.addAtHead(val)
    var node = this.Head.next
    var i = 0
    while(node){
        if(i===index-1){
            var next = node.next
            var newNode = {val,next:null}
            newNode.next = next
            node.next = newNode
            break
        }
        node = node.next
        i++
    }
};

/** 
 * @param {number} index
 * @return {void}
 */
MyLinkedList.prototype.deleteAtIndex = function (index) {
    var i = -1
    var node = this.Head
    while(node){
        if(i===index-1&&node.next){
            node.next = node.next.next
            break
        }
        node = node.next
        i++
    }
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * var obj = new MyLinkedList()
 * var param_1 = obj.get(index)
 * obj.addAtHead(val)
 * obj.addAtTail(val)
 * obj.addAtIndex(index,val)
 * obj.deleteAtIndex(index)
 */