链表的区别

链表也分为单链表双链表

  • 单链表:每个节点包含 value 和 next,next 指向下一个节点
  • 双链表:每个节点包含 prev、value 和 next,prev 指向前一个节点,next 指向下一个节点

单链表的实现

class Node{
    constructor(value){
        this.value = value
        this.next = null
    }
}

class MyLinkedList{
    constructor(){
        this.head = null
        this.length = 0
    }
    // 按索引获取节点 value
    get(index){
        if(index >= 0 && index < this.length){
            let current = this.head
            if(index === 0){
                return current.value
            }else{
                let position = 0
                while(position < index){
                    current = current.next
                    position++
                }
                return current.value
            }
        }
        return -1
    }
    // 在头部添加节点
    addAtHead(val){
        const node = new Node(val)
        let current = this.head
        this.head = node
        this.head.next = current
        this.length++
    }
    // 添加节点到尾部
    addAtTail(val){
        const node = new Node(val)
        if(this.length){
            let current = this.head
            while(current.next){
                current = current.next
            }
            current.next = node
        }else{
            this.head = node
        }
        this.length++
    }
    // 在给定位置添加节点
    addAtIndex(index, val){
        const node = new Node(val)
        let position = 0
        let current = null
        let previous = null
        let length = this.length
        if(length === 0 && index <= 0){
            this.head = node
            this.length++
        }else if (index <= 0){
           this.addAtHead(val)
        }else if(index === length){
            this.addAtTail(val)
        }else if(index > 0 && index < length){
            current = this.head
            while(position < index){
                previous = current
                current = current.next
                position++
            }
            previous.next = node
            node.next = current
            this.length++
        }
    }
    // 按索引删除
    deleteAtIndex(index){
        if(index >= this.length) return
        let current = this.head
        let previous = null
        let position = 0
        if(index === 0 && index === this.length){
            this.head = null
        }else if(index === 0 ){
            this.head = current.next
        }else{
            while(position < index){
                previous = current
                current = current.next
                position++
            }
            previous.next = current.next
        }
        this.length--
    }
}

双链表的实现

class Node{
    constructor(value){
        this.value = value
        this.next = null
        this.prev = null
    }
}

class MyLinkedList{
    constructor(){
        this.head = null
        this.length = 0
    }
    get(index){
        if(index >= 0 && index < this.length){
            let current = this.head
            if(index === 0){
                return current.value
            }else{
                let position = 0
                while(position < index){
                    current = current.next
                    position++
                }
                return current.value
            }
        }
        return -1
    }
    addAtHead(val){
        const node = new Node(val)
        let current = this.head
        this.head = node
        this.head.next = current
        this.length++
        if(this.length === 1){
            return
        }else{
            current.prev = this.head
        }
    }
    addAtTail(val){
        const node = new Node(val)
        if(this.length){
            let current = this.head
            while(current.next){
                current = current.next
            }
            current.next = node
            node.prev = current
        }else{
            this.head = node
        }
        this.length++
    }
    addAtIndex(index, val){
        const node = new Node(val)
        let position = 0
        let current = null
        let previous = null
        let length = this.length
        if(length === 0 && index <= 0){
            this.head = node
            this.length++
        }else if (index <= 0){
           this.addAtHead(val)
        }else if(index === length){
            this.addAtTail(val)
        }else if(index > 0 && index < length){
            current = this.head
            while(position < index){
                previous = current
                current = current.next
                position++
            }
            previous.next = node
            current.prev = node
            node.prev = previous
            node.next = current
            this.length++
        }
    }
    deleteAtIndex(index){
        if(index >= this.length) return
        let current = this.head
        let previous = null
        let position = 0
        if(index === 0 && this.length === 1){
           this.head = null
        }else if(index === 0){
            this.head = current.next
            current.next.prev = null
        }else{
            while(position < index){
                previous = current
                current = current.next
                position++
            }
            if(index === this.length - 1){
                previous.next = null
            }else{
                previous.next = current.next
                current.next.prev = previous
            }
        }
        this.length--
    }
}

环形链表

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。 说明:不允许修改给定的链表。

解法:双指针遍历 首先明确一个结论:head到入环点的距离 等于 相遇点到入环点的距离,推演过程有空补图=。=

var detectCycle = function(head) {
    if(!head || !head.next) return null
    let fastPoint = head
    let slowPoint = head
    while(fastPoint && fastPoint.next){
        fastPoint = fastPoint.next.next
        slowPoint = slowPoint.next
        if(fastPoint === slowPoint) {
            slowPoint = head
            while(fastPoint !== slowPoint){
                fastPoint = fastPoint.next
                slowPoint = slowPoint.next
            }
            return slowPoint
        }
    }
    return null
};