(声明:所有题目都是leetcode上非会员题目)
链表是一种基础的数据结构,下面引用百度百科对链表的定义:
链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。每个结点包括两个部分:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。 相比于线性表顺序结构,操作复杂。由于不必须按顺序存储,链表在插入的时候可以达到O(1)的复杂度,比另一种线性表顺序表快得多,但是查找一个节点或者访问特定编号的节点则需要O(n)的时间,而线性表和顺序表相应的时间复杂度分别是O(logn)和O(1)
使用链表结构可以克服数组链表需要预先知道数据大小的缺点,链表结构可以充分利用计算机内存空间,实现灵活的内存动态管理。但是链表失去了数组随机读取的优点,同时链表由于增加了结点的指针域,空间开销比较大。链表最明显的好处就是,常规数组排列关联项目的方式可能不同于这些数据项目在记忆体或磁盘上顺序,数据的存取往往要在不同的排列顺序中转换。链表允许插入和移除表上任意位置上的节点,但是不允许随机存取。链表有很多种不同的类型:单向链表,双向链表以及循环链表。
本文将会以前端工程师的角度,使用JavaScript来解答leetcode上链表相关的问题,以求加深对链表的理解,本文将会持续增加新题目的解答与分析。
一. 链表的实现
首先来看如何用javascript实现一个链表,我们使用两个指针head,tail分别标示链表的头尾节点,length属性维护链表的长度
在链表类中我们实现这些功能:
get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点
leetcode 707. 设计链表
题目地址:设计链表
/**
* Initialize your data structure here.
*/
var MyLinkedList = function() {
this.head = null
this.tail = null
this.length = 0
};
var listNode = function(val) {
this.val = val
this.next = null
}
/**
* Get the value of the index-th node in the linked list. If the index is invalid, return -1.
* @param {number} index
* @return {number}
*/
MyLinkedList.prototype.get = function(index) {
if (index >=0 && index < this.length) {
let i = 0
let cur = this.head
while (i < index) {
cur = cur.next
i ++
}
return cur.val
} else {
return -1
}
};
/**
* Add a node of value val before the first element of the linked list. After the insertion, the new node will be the first node of the linked list.
* @param {number} val
* @return {void}
*/
MyLinkedList.prototype.addAtHead = function(val) {
const lastHead = this.head
const node = new listNode(val)
this.head = node
this.head.next = lastHead
if (!this.tail) {
this.tail = node
this.tail.next = null
}
this.length ++
};
/**
* Append a node of value val to the last element of the linked list.
* @param {number} val
* @return {void}
*/
MyLinkedList.prototype.addAtTail = function(val) {
const lastTail = this.tail
const node = new listNode(val)
this.tail = node
if (lastTail) {
lastTail.next = this.tail
}
if (!this.head) {
this.head = node
this.head.next = null
}
this.length ++
};
/**
* Add a node of value val before the index-th node in the linked list. If index equals to the length of linked list, the node will be appended to the end of linked list. If index is greater than the length, the node will not be inserted.
* @param {number} index
* @param {number} val
* @return {void}
*/
MyLinkedList.prototype.addAtIndex = function(index, val) {
if (index === this.length) {
this.addAtTail(val)
} else if (index <= 0) {
this.addAtHead(val)
} else if (index > 0 && index < this.length) {
let i = 0
let prev = this.head
while (i < index - 1) {
prev = prev.next
i ++
}
const node = new listNode(val)
node.next = prev.next
prev.next = node
this.length ++
}
};
/**
* Delete the index-th node in the linked list, if the index is valid.
* @param {number} index
* @return {void}
*/
MyLinkedList.prototype.deleteAtIndex = function(index) {
if (index > 0 && index < this.length) {
let i = 0
let prev = null
let cur = this.head
while (i < index) {
prev = cur
cur = cur.next
i ++
}
prev.next = cur.next
if (index === this.length - 1) {
this.tail = prev
}
this.length --
} else if (index === 0) {
this.head = this.head.next
this.length --
}
};
二. 链表相关的其它题目
leetcode 2. 两数相加
题目地址:两数相加
注意,对于链表的定义,在leetcode题目的注释中有给出,一个listNode,具有val属性,实例化时将用户传入的值赋予它,还有一个next属性,指向链接的下一个节点,默认值为null
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var addTwoNumbers = function(l1, l2) {
let l3 = null
if (l1 == null && l2 == null) {
// l1 与 l2 都为 null 的情况
return null;
} else if (l1 == null && l2 != null) {
// l1 为 null 但是 l2 不为 null 的情况
return l2;
} else if (l1 != null && l2 == null) {
// l1 不为 null 但是 l2 为 null 的情况
return l1;
} else {
// l1 l2 都不为 null 的情况
if (l1.val + l2.val < 10) {
// 不需要进位的情况
l3 = new ListNode(l1.val + l2.val);
l3.next = addTwoNumbers(l1.next, l2.next);
}else {
// 需要进位的情况
l3 = new ListNode(l1.val + l2.val - 10);
l3.next = addTwoNumbers(l1.next, addTwoNumbers(l2.next, new ListNode(1)));
}
}
return l3
};
leetcode 19. 删除链表的倒数第N个节点
题目地址:删除链表的倒数第N个节点
解法一:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
const arr = [head]
for (let cur = head; cur.next; cur = cur.next) {
arr.push(cur.next)
}
const len = arr.length
if (len === 1) {
return null
}
if (n > 1) {
arr[len - n].val = arr[len - n].next.val
arr[len - n].next = arr[len - n].next.next
} else {
arr[len - n - 1].next = null
}
return arr[0]
};
解法二:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} n
* @return {ListNode}
*/
var removeNthFromEnd = function(head, n) {
let first = head;
for (let i = 0; i < n; i++) {
first = first.next;
}
if (!first) return head.next; // 当n=链表长度时,此时需要删除第一个节点
let second = head;
while (first.next) {
first = first.next;
second = second.next;
}
second.next = second.next.next;
return head;
};
leetcode 21. 合并两个有序链表
题目地址:合并两个有序链表
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var mergeTwoLists = function(l1, l2) {
const res = new ListNode(0)
let prev = res
while (l1 && l2) {
if (l1.val > l2.val) {
prev.next = l2
l2 = l2.next
} else {
prev.next = l1
l1 = l1.next
}
prev = prev.next
}
if (l1) {
prev.next = l1
}
if (l2) {
prev.next = l2
}
return res.next
};
leetcode 23. 合并K个排序链表
题目地址:合并K个排序链表
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode[]} lists
* @return {ListNode}
*/
var mergeKLists = function(lists) {
const len = lists.length
if (len === 0) {
return null
}
const temp = []
for (let i = 0; i < len; i ++) {
const list = lists[i]
let cur = list
while(cur) {
temp.push(cur.val)
cur = cur.next
}
}
const tLen = temp.length
if (tLen === 0) {
return null
}
temp.sort((a, b) => a - b)
const head = new ListNode(temp[0])
let cur = head
for (let i = 1; i < tLen; i ++) {
const node = new ListNode(temp[i])
cur.next = node
cur = cur.next
}
return head
};
leetcode 24. 两两交换链表中的节点
题目地址:两两交换链表中的节点
解法一:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var swapPairs = function(head) {
if (!head) {
return null
}
const array = [head]
while (head.next) {
array.push(head.next)
head.next = head.next.next
}
const len = array.length
for(let i = 0; i < len; i = i + 2){
if(i + 1 < len){
let temp = array[i];
array[i] = array[i + 1];
array[i + 1] = temp;
}
}
array.forEach((item, index) => {
if (index === len - 1) {
item.next = null
} else {
item.next = array[index + 1]
}
})
return array[0]
};
解法二:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var swapPairs = function(head) {
// 链表长度小于2,我们都直接返回head就行
if (head == null || head.next == null) {
return head;
}
const next = head.next;
// 递归处理后面所有的节点
head.next = swapPairs(next.next);
// 交换前两个节点
next.next = head;
return next;
};
leetcode 25. K 个一组翻转链表
题目地址:K 个一组翻转链表
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
var reverseKGroup = function(head, k) {
const temp = []
while (head) {
temp.push(head.val)
head = head.next
}
const len = temp.length
const m = Math.floor(len / k)
const n = len % k
const tail = temp.slice(m * k)
let res = []
let count = 0
let arr = []
for (let i = 0; i < m * k; i++) {
if (count === k) {
count = 0
while (arr.length) {
res.push(arr.pop())
}
}
count ++
arr.push(temp[i])
}
while (arr.length) {
res.push(arr.pop())
}
res = res.concat(tail)
let node = new ListNode(res[0])
let prev = node
for (let i = 1; i < res.length; i++) {
node.next = new ListNode(res[i])
node = node.next
}
return prev
};
解法二:k个一组进行遍历翻转
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} k
* @return {ListNode}
*/
var reverseKGroup = function(head, k) {
// 标兵
let dummy = new ListNode()
dummy.next = head
let [start, end] = [dummy, dummy.next]
let count = 0
while(end) {
count++
if (count % k === 0) {
start = reverseList(start, end.next)
end = start.next
} else {
end = end.next
}
}
return dummy.next
// 翻转stat -> end的链表
function reverseList(start, end) {
let [pre, cur] = [start, start.next]
const first = cur
while(cur !== end) {
let next = cur.next
cur.next = pre
pre = cur
cur = next
}
start.next = pre
first.next = cur
return first
}
};
leetcode 83. 删除排序链表中的重复元素
题目地址:删除排序链表中的重复元素
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var deleteDuplicates = function(head) {
let current = head
while(current && current.next) {
if (current.val === current.next.val) {
current.next = current.next.next
} else{
current = current.next
}
}
return head
};
leetcode 82. 删除排序链表中的重复元素 II
题目地址:删除排序链表中的重复元素 I
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var deleteDuplicates = function(head) {
let prev = new ListNode();
prev.next = head; // 插入了一个虚拟的头结点以便操作
if(!prev.next)
return prev.next; // 检查链表是否为空
let p = prev, f = p.next, b = f.next, flag = false;
while(f && b) {
if(f.val != b.val) { // 若前向指针f和后向指针b的值不同
if(!flag) { // 若之前未发生相同数值的情况
p = f; // 重置p指针
} else {
p.next = b; // 否则把p到b中的所有元素删除
}
flag = false; // 清空标志
} else {
flag = true; // 发生了值相同的情况
}
f = b;
b = b.next; // 前后指针向后移动一格
};
if(flag)
p.next = b; // 收尾处理一下
return prev.next;
};
leetcode 92. 反转链表 II
题目地址:反转链表 II
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseBetween = function(head, m, n) {
const temp = new ListNode(0)
temp.next = head
let left = temp
for (let i = 0; i < m - 1; i++) {
left = left.next
}
let prev = null
let cur = left.next
for (let i = 0; i < n - m + 1; i++) {
let next = cur.next
cur.next = prev
prev = cur
cur = next
}
// 将 m的next指向n的next, 同时将排在m前面节点的指针next指向n
left.next.next = cur
left.next = prev
return temp.next
}
leetcode 141. 环形链表
题目地址:环形链表
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var hasCycle = function(head) {
let pos = 0
let cur = head
while (cur) {
if (cur.pos === undefined) {
cur.pos = pos
pos ++
cur = cur.next
} else {
return true
}
}
return false
};
解法二: 如果是环形链表,序列化会失败
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var hasCycle = function(head) {
try{
JSON.stringify(head);
return false;
} catch(err){
return true;
}
}
leetcode 142. 环形链表 II
题目地址:环形链表 II
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var detectCycle = function(head) {
let pos = 0
let cur = head
while (cur) {
if (cur.pos === undefined) {
cur.pos = pos
pos ++
cur = cur.next
} else {
return cur
}
}
return null
};
leetcode 143. 重排链表
题目地址:重排链表
解法一:这个问题用到了快慢指针
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {void} Do not return anything, modify head in-place instead.
*/
var reorderList = function (head) {
if (!head || !head.next) {
return
}
// 1. 快慢指针找到链表中点
let node1 = head
let node2 = head.next
while (node2 && node2.next) {
node1 = node1.next
node2 = node2.next.next
}
// 后半部分链表
node2 = node1.next
// 注意,这一步很重要,node1.next = null,之后node1 = head,才能使得node1只保留链表前半部分
node1.next = null
node1 = head
// 2. 翻转后半部分链表
let prev = null
let cur = node2
while (cur) {
let temp = cur.next
cur.next = prev
prev = cur
cur = temp
}
// 3.前后两部分链表合并(前后部分长度相同或者后半部分多一个)
node2 = prev
while (node2) {
let next1 = node1.next
let next2 = node2.next
node1.next = node2
node2.next = next1
node1 = next1
node2 = next2
}
}
解法二: 使用数组
var reorderList = function(head) {
if (!head || !head.next) {
return
}
// temp1保存链表节点原来的顺序
const temp1 = []
while (head) {
temp1.push(head)
head = head.next
}
// temp2保存链表节点交换顺序后的顺序
const temp2 = []
const len = temp1.length
for (let i = 0; i < len; i++) {
temp2.push(temp1[i])
if (i !== len - i - 1) {
temp2.push(temp1[len - i - 1])
}
}
// 将各个节点next指针联系起来
const node = temp2[0]
let cur = node
for (let j = 1; j < len; j++) {
cur.next = temp2[j]
cur = cur.next
cur.next = null
}
head = node
};
leetcode 148. 排序链表
题目地址:排序链表
这个问题可以使用归并排序,其中使用快慢指针法找到处于中间位置的节点,如果是偶数个节点,取前一半最后一个是中间节点
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var sortList = function(head) {
// 典型归并排序
let mergeList = (left,right) => {
let prev = new ListNode(null)
const temp = prev
while (left && right) {
if (left.val <= right.val) {
prev.next = left
left = left.next
} else {
prev.next = right
right = right.next
}
prev = prev.next
}
// 这里注意,left和right最多差一个节点
prev.next = left ? left : right
return temp.next
}
let mergeSort = (node) => {
if(!node || !node.next) return node;
// 快慢指针
let mid = node
let fast = mid.next
// 快指针遍历完毕时,满指针mid正好是中间节点
while (fast && fast.next) {
mid = mid.next
fast = fast.next.next
}
let rightList = mid.next
mid.next = null
let leftList = node
return mergeList(mergeSort(leftList), mergeSort(rightList))
}
return mergeSort(head);
};
leetcode 160. 相交链表
题目地址:相交链表
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
*/
var getIntersectionNode = function(headA, headB) {
while(headA){
var temp = headB;
while(temp){
if(temp===headA) return headA;
temp=temp.next
}
headA=headA.next;
}
};
解法二:双指针相遇
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
*/
var getIntersectionNode = function(headA, headB) {
let pA = headA;
let pB = headB;
while(pA !== pB){
pB = pB ? pB.next : headA;
pA = pA ? pA.next : headB;
}
return pA;
};
解法三:标记节点
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} headA
* @param {ListNode} headB
* @return {ListNode}
*/
var getIntersectionNode = function(headA, headB) {
while (headA) {
headA.used = true
headA = headA.next
}
while (headB) {
if (headB.used) {
return headB
}
headB = headB.next
}
return null
};
leetcode 203. 移除链表元素
题目地址:移除链表元素
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} val
* @return {ListNode}
*/
var removeElements = function(head, val) {
if (head == null) return null;
head.next = removeElements(head.next, val);
return head.val == val ? head.next : head;
};
leetcode 206. 反转链表
题目地址:反转链表
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
let [prev, curr] = [null, head];
while (curr) {
[curr.next, prev, curr] = [prev, curr, curr.next];
}
return prev;
};
leetcode 234. 回文链表
题目地址:回文链表
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var isPalindrome = function(head) {
const temp = []
let cur = head
while (cur) {
temp.push(cur.val)
cur = cur.next
}
for (let i = 0; i < temp.length; i++) {
if (temp[i] !== temp[temp.length - 1 - i]) {
return false
}
}
return true
};
leetcode 237. 删除链表中的节点
题目地址:删除链表中的节点
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} node
* @return {void} Do not return anything, modify node in-place instead.
*/
var deleteNode = function(node) {
node.val = node.next.val
node.next = node.next.next
};
解法二:使用ES6特性
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} node
* @return {void} Do not return anything, modify node in-place instead.
*/
var deleteNode = function(node) {
Object.assign(node, node.next);
};
leetcode 445. 两数相加 II
题目地址:两数相加 II
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var addTwoNumbers = function(l1, l2) {
const arr1 = []
const arr2 = []
const arr3 = []
let cur1 = l1
let cur2 = l2
while (cur1) {
arr1.push(cur1.val)
cur1 = cur1.next
}
while (cur2) {
arr2.push(cur2.val)
cur2 = cur2.next
}
// arr1 和 arr2 相加,结果放入arr3
let carry = 0;
while (arr1.length > 0 || arr2.length > 0 || carry > 0) {
let n1 = arr1.pop(),
n2 = arr2.pop();
let { curr, last } = sum(n1, n2, carry);
arr3.unshift( curr );
carry = last;
}
const len = arr3.length
let head = new ListNode(+arr3[0])
let cur = head
for (let i = 1; i < len; i++) {
cur.next = new ListNode(+arr3[i])
cur = cur.next
}
return head
};
// 辅助函数,计算三个数之和,返回和的个位和十位
function sum(a = 0, b = 0, c = 0) {
let s = a + b + c;
let curr, last;
if (s > 9) {
s = String(s);
curr = Number(s.slice(s.length - 1));
last = Number(s.slice(0, s.length - 1));
} else {
curr = s;
last = 0;
}
return {
curr: curr,
last: last
}
}
leetcode 876. 链表的中间结点
题目地址:链表的中间结点
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var middleNode = function(head) {
const temp = []
let len = 0
let current = head
while (current) {
len ++
temp.push(current)
current = current.next
}
return len % 2 ? temp[Math.floor(len / 2)] : temp[len / 2]
};
leetcode 1171. 从链表中删去总和值为零的连续节点
题目地址:从链表中删去总和值为零的连续节点
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var removeZeroSumSublists = function(head) {
// 链表转换为数组
const temp = []
while (head) {
temp.push(head.val)
head = head.next
}
// 去除和为0的所有序列
for (let i = 0; i < temp.length; i++) {
let start = i
let end = i
let sum = temp[i]
if (sum === 0) {
temp.splice(i, 1)
i --
} else {
for (let j = i + 1; j < temp.length; j++) {
sum += temp[j]
end ++
if (sum === 0) {
temp.splice(i, end - start + 1)
i --
break
}
}
}
}
// 数组转换为链表
let node = null
if (temp.length) {
node = new ListNode(temp[0])
let cur = node
let i = 1
while (temp[i]) {
cur.next = new ListNode(temp[i])
cur = cur.next
i ++
}
}
return node
};
leetcode 1290. 二进制链表转整数
题目地址:二进制链表转整数
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {number}
*/
var getDecimalValue = function(head) {
const stack = []
let cur = head
while (cur) {
stack.unshift(cur.val)
cur = cur.next
}
let sum = 0
stack.forEach((num, index) => {
sum += num * Math.pow(2, index)
})
return sum
};