链表算法整理
真的非常气愤,花了很多时间去差错,到最后发现居然是因为判断条件只写了一个等于号和construtor 写成了contructer,硬是找了半天错误,感觉时间都被浪费掉了,诶
1.移除链表元素
-
简单的移除元素 ,只需要找到他的pre节点,值得思考的是最好加上一个头节点!如果不使用头结点,就直接把head指针向后移动一个,所以在单链表中移除头结点 和 移除其他节点的操作方式是不一样,其实在写代码的时候也会发现,需要单独写一段逻辑来处理移除头结点的情况
-
var removeElements = function(head, val) { let node = new ListNode(0,head) let pre = node let cur = pre.next while(cur!==null) { if(cur.val === val){ console.log("pre",pre.val) pre.next = cur.next cur = cur.next }else{ cur = cur.next pre = pre.next } } return node.next };
2.设计链表 (坑惨了)

-
下次一定要细心一点 诶
-
lass LinkNode { constructer(val ,next){ this.val = val this.next = next } } var MyLinkedList = function() { this._size = 0 this._head = null this._tail = null }; class LinkNode { constructor(val, next) { this.val = val; this.next = next; } } /** * Initialize your data structure here. * 单链表 储存头尾节点 和 节点数量 */ var MyLinkedList = function() { this._size = 0; this._tail = null; this._head = null; }; /** * @param {number} index * @return {number} */ MyLinkedList.prototype.get = function(index) { if(index < 0 || index >= this._size) return -1; // 获取当前节点 return this.getNode(index).val; }; /** * @param {number} val * @return {void} */ MyLinkedList.prototype.addAtHead = function(val) { const node = new LinkNode(val, this._head); this._head = node; this._size++; if(!this._tail) { this._tail = node; } }; /** * 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 node = new LinkNode(val, null); this._size++; if(this._tail) { this._tail.next = node; this._tail = node; return; } this._tail = node; this._head = node; }; /** * @param {number} index * @param {number} val * @return {void} */ MyLinkedList.prototype.getNode = function(index) { if(index < 0 || index >= this._size) return null; // 创建虚拟头节点 let cur = new LinkNode(0, this._head); // 0 -> head while(index-- >= 0) { cur = cur.next; } return cur; }; MyLinkedList.prototype.addAtIndex = function(index, val) { if(index > this._size) return; if(index <= 0) { this.addAtHead(val); return; } if(index === this._size) { this.addAtTail(val); return; } // 获取目标节点的上一个的节点 const node = this.getNode(index - 1); node.next = new LinkNode(val, node.next); this._size++; }; /** * @param {number} index * @return {void} */ MyLinkedList.prototype.deleteAtIndex = function(index) { if(index < 0 || index >= this._size) return; if(index === 0) { this._head = this._head.next; // 如果删除的这个节点同时是尾节点,要处理尾节点 if(index === this._size - 1){ this._tail = this._head } this._size--; return; } // 获取目标节点的上一个的节点 const node = this.getNode(index - 1); node.next = node.next.next; // 处理尾节点 if(index === this._size - 1) { this._tail = node; } this._size--; };
3.反转链表
-
依然是找到他的前一个节点就好了,双指针,但是不习惯使用递归方法,尝试使用
-
var reverseList = function(head) { let pre = null let cur = head while(cur!==null) { let temp = cur.next cur.next = pre pre = cur cur = temp } return pre }; //记得return喔!!!!!!!!! var reverseList = function(head) { function reverse(pre,cur) { if(!cur) return pre let temp = cur.next cur.next = pre return reverse(cur, temp) } return reverse(null,head) };
4.两两交换链表的节点
-
var swapPairs = function(head) { let node = new ListNode(0,head) let pre = node while(pre.next&& pre.next.next) { let cur1 = pre.next let cur2 = pre.next.next pre.next = cur2 cur1.next = cur2.next cur2.next = cur1 pre = cur1 } return node.next };
5.删除链表的倒数第N个节点
-
使用双指针方法,倒数第几个元素就让 fast节点先走几步,然后同时移动fast,slow指针slow指针指向的就是要删除的节点的前一个节点,此题印象比较深刻之前做过。
-
var removeNthFromEnd = function(head, n) { let node = new ListNode(0,head) let pre = node let rear = node while(n>0){ n-- rear = rear.next } while(rear.next!== null) { rear = rear.next pre = pre.next } pre.next = pre.next.next return node.next }; ```# 链表算法整理
真的非常气愤,花了很多时间去差错,到最后发现居然是因为判断条件只写了一个等于号和construtor 写成了contructer,硬是找了半天错误,感觉时间都被浪费掉了,诶
1.移除链表元素
-
简单的移除元素 ,只需要找到他的pre节点,值得思考的是最好加上一个头节点!如果不使用头结点,就直接把head指针向后移动一个,所以在单链表中移除头结点 和 移除其他节点的操作方式是不一样,其实在写代码的时候也会发现,需要单独写一段逻辑来处理移除头结点的情况
-
var removeElements = function(head, val) { let node = new ListNode(0,head) let pre = node let cur = pre.next while(cur!==null) { if(cur.val === val){ console.log("pre",pre.val) pre.next = cur.next cur = cur.next }else{ cur = cur.next pre = pre.next } } return node.next };
2.设计链表 (坑惨了)

-
下次一定要细心一点 诶
-
lass LinkNode { constructer(val ,next){ this.val = val this.next = next } } var MyLinkedList = function() { this._size = 0 this._head = null this._tail = null }; class LinkNode { constructor(val, next) { this.val = val; this.next = next; } } /** * Initialize your data structure here. * 单链表 储存头尾节点 和 节点数量 */ var MyLinkedList = function() { this._size = 0; this._tail = null; this._head = null; }; /** * @param {number} index * @return {number} */ MyLinkedList.prototype.get = function(index) { if(index < 0 || index >= this._size) return -1; // 获取当前节点 return this.getNode(index).val; }; /** * @param {number} val * @return {void} */ MyLinkedList.prototype.addAtHead = function(val) { const node = new LinkNode(val, this._head); this._head = node; this._size++; if(!this._tail) { this._tail = node; } }; /** * 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 node = new LinkNode(val, null); this._size++; if(this._tail) { this._tail.next = node; this._tail = node; return; } this._tail = node; this._head = node; }; /** * @param {number} index * @param {number} val * @return {void} */ MyLinkedList.prototype.getNode = function(index) { if(index < 0 || index >= this._size) return null; // 创建虚拟头节点 let cur = new LinkNode(0, this._head); // 0 -> head while(index-- >= 0) { cur = cur.next; } return cur; }; MyLinkedList.prototype.addAtIndex = function(index, val) { if(index > this._size) return; if(index <= 0) { this.addAtHead(val); return; } if(index === this._size) { this.addAtTail(val); return; } // 获取目标节点的上一个的节点 const node = this.getNode(index - 1); node.next = new LinkNode(val, node.next); this._size++; }; /** * @param {number} index * @return {void} */ MyLinkedList.prototype.deleteAtIndex = function(index) { if(index < 0 || index >= this._size) return; if(index === 0) { this._head = this._head.next; // 如果删除的这个节点同时是尾节点,要处理尾节点 if(index === this._size - 1){ this._tail = this._head } this._size--; return; } // 获取目标节点的上一个的节点 const node = this.getNode(index - 1); node.next = node.next.next; // 处理尾节点 if(index === this._size - 1) { this._tail = node; } this._size--; };
3.反转链表
-
依然是找到他的前一个节点就好了,双指针,但是不习惯使用递归方法,尝试使用
-
var reverseList = function(head) { let pre = null let cur = head while(cur!==null) { let temp = cur.next cur.next = pre pre = cur cur = temp } return pre }; //记得return喔!!!!!!!!! var reverseList = function(head) { function reverse(pre,cur) { if(!cur) return pre let temp = cur.next cur.next = pre return reverse(cur, temp) } return reverse(null,head) };
4.两两交换链表的节点
-
var swapPairs = function(head) { let node = new ListNode(0,head) let pre = node while(pre.next&& pre.next.next) { let cur1 = pre.next let cur2 = pre.next.next pre.next = cur2 cur1.next = cur2.next cur2.next = cur1 pre = cur1 } return node.next };
5.删除链表的倒数第N个节点
-
使用双指针方法,倒数第几个元素就让 fast节点先走几步,然后同时移动fast,slow指针slow指针指向的就是要删除的节点的前一个节点,此题印象比较深刻之前做过。
-
var removeNthFromEnd = function(head, n) { let node = new ListNode(0,head) let pre = node let rear = node while(n>0){ n-- rear = rear.next } while(rear.next!== null) { rear = rear.next pre = pre.next } pre.next = pre.next.next return node.next };
6.链表相交
-
俩种思路:
-
使用set,把一条链表的节点全部加入到set中,然后看便利第二条链表
-
两条相交的链表尾部从相交开始就是一样的 也就是说两条链表的长度差一定小于交点之前的长度差。
平衡两条链表的长度,一起next即可找到交点
var getIntersectionNode = function(headA, headB) { // let visited = new Set() // while(headA){ // visited.add(headA) // headA = headA.next // } // while(headB){ // if(visited.has(headB)) return headB // headB = headB.next // } // return null function getLength(head) { let len = 0 while(head){ len++ head = head.next } return len } let len1 = getLength(headA) console.log(len1) let len2 = getLength(headB) console.log(len2) if(len1 < len2){ [len1,len2] = [len2,len1]; [headA,headB] = [headB,headA] } let sub = len1 - len2 console.log(sub) while(sub > 0) { sub-- headA = headA.next } while(headA&&headB) { if(headA == headB) return headA headA = headA.next headB = headB.next } return null };
-
7. 环形链表
-
首先需要判断是否有环,此题印象比较深,一快一慢指针同时出发,如果有环一定可以相遇
-
其次找到环的起点:
- 借助一下随想录的图,假设fast的速度是slow的两倍,而且最终他们相遇了,且肯定还是在圆中,不然不可能相遇,基于这个情况下可以列出等式 2(x+y) = n(y+z) + x+y,那么x+y = n(y+z)
- 1.可能这个圈很大,那么n最小也就是1:x = y
- 2.可能这个圈很小,x = n(y+z) -z: 这个等式的意思就是再说一样的速度走的话,一个人a从x起点开始走,另一个b从他们的交点开始走,a走直线,b就是在圆中走,a走到环的入口处,b走了n个圆距离-y,b的起点是交点,交点-y还是入口处
- 所以可知找到交点 即可找到入口~!上代码
-
var detectCycle = function(head) { if(!head || !head.next) return null; let slow =head.next, fast = head.next.next; while(fast!==slow&&fast&&fast.next){ fast = fast.next.next slow = slow.next } if(!fast||!fast.next) return null let cur = head while(cur!==slow){ cur = cur.next slow = slow.next } return slow };