class Node {
constructor (node) {
if (Node.isNode(node)) {
[this.data, this.next] = [node.data, node.next]
} else {
[this.data, this.next] = [node, null]
}
}
static isNode (node) {
return !!(node && Object.isPrototypeOf.call(Node.prototype, node))
}
}
class LinkList
{
constructor (...nodeArray) {
if (!nodeArray.length) this.head = null
else this.append(...nodeArray)
}
append (...nodeArray) {
while (nodeArray.length) {
const newNode = new Node(nodeArray.shift())
if (!newNode) continue
if (!this.head) {
this.head = newNode
continue
}
let curNode = this.head
while (curNode && curNode.next) {
curNode = curNode.next
}
curNode.next = newNode
}
}
find (node) {
if (!node) return
let target = null
let curNode = this.head
while (curNode) {
if (curNode.data === node) {
target = curNode
break
}
if (!curNode.next) break
curNode = curNode.next
}
return target
}
insert (target, node) {
if (!node) return
if (!target) return this.append(node)
const nodeCopy = new Node(node)
const targetNode = this.find(target)
if (!targetNode) return this.append(node)
const targetNextNode = targetNode.next
nodeCopy.next = targetNextNode
targetNode.next = nodeCopy
}
insertBefore (target, node) {
if (!node) return
if (!target) return this.append(node)
let curNode = this.head
let lastNode = null
while (curNode && curNode.next) {
if (target === curNode.data) {
break
} else {
lastNode = curNode
curNode = curNode.next
}
}
if (lastNode) {
const newNode = new Node(node)
newNode.next = lastNode.next
lastNode.next = newNode
} else {
this.append(node)
}
}
delete (target) {
if (!target) return
if (target.next) {
target.data = target.next.data
target.next = target.next.next
} else if (target === this.head) {
this.head = null
} else {
let curNode = this.head
while (curNode && curNode.next && curNode.next.next) {
curNode = curNode.next
}
if (curNode.next === target) {
curNode.next = null
}
}
}
deleteRepeatNode () {
const map = {}
if (this.head && this.head.next) {
let curNode = this.head
while (curNode) {
map[curNode.data] = map[curNode.data] ? map[curNode.data] + 1 : 1
curNode = curNode.next
}
curNode = this.head
while (curNode) {
if (map[curNode.data] > 1) {
map[curNode.data]--
this.delete(curNode)
} else {
curNode = curNode.next
}
}
}
}
browse (type = 'push', node = this.head) {
if (!node) return []
let curNode = this.head
const result = []
while (curNode) {
result[type](curNode.data)
curNode = curNode.next
}
return result
}
reverse () {
if (!this.head) return
let curNode = null
let reversedList = this.head
while (this.head && this.head.next) {
curNode = this.head.next
this.head.next = curNode.next
curNode.next = reversedList
reversedList = curNode
}
this.head = reversedList
return this
}
}
const myLinkList = new LinkList(0, 8, 1, 2)
console.log(myLinkList.browse())
myLinkList.insert(1, 3)
myLinkList.insertBefore(3, 4)
console.log(myLinkList.browse())
console.log(myLinkList.browse('unshift'))
console.log(myLinkList.reverse().browse())
const node2 = myLinkList.find(2)myLinkList.delete(node2)
console.log(myLinkList.browse())myLinkList.append(3, 4, 3, 6, 7)
console.log(myLinkList.browse())myLinkList.deleteRepeatNode()
console.log(myLinkList.browse())
const josephCircle = (sum, order) => {
const circleList = new LinkList(...Array.from({ length: sum }, (val, index) => index))
const node = circleList.find(sum - 1)
node.next = circleList.head
let curNode = node
while (curNode.next !== curNode) {
for (let i = 0; i < order - 1; i++) {
curNode = curNode.next
}
curNode.next = curNode.next.next
}
return curNode.data
}
console.log(josephCircle(10, 3))
