leetcode 203
给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。
var removeElements = function(head, val) {
// 虚拟节点
const ret = new ListNode(0,head)
let cur = ret
while(cur.next){
if(cur.next.val === val){
cur.next = cur.next.next
continue
}
cur = cur.next
}
return ret.next
};
具体代码直接就抄了
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;
};
/**
* 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.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.get = function(index) {
if(index < 0 || index >= this._size) return -1;
// 获取当前节点
return this.getNode(index).val;
};
/**
* 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 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;
};
/**
* 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._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++;
};
/**
* 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._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--;
};
leetcode 206
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。
// 双指针
var reverseList = function(head) {
if(!head || !head.next) return head
let tmp = null, pre = null, cur = head
while(cur){
temp = cur.next
cur.next = pre
pre = cur
cur = temp
}
return pre
};
// 递归
var reverse = function(pre,head){
if(!head) return pre
const tmp = head.next
head.next = pre
pre = head
return reverse(pre,tmp)
}
var reverseList = function(head) {
return reverse(null,head)
};
递归感觉能更好理解一点,牢记链表结构val和next组成,next!!!!!指向下一个节点,也可理解为指向下一个对象
leetcode24
左1是没换,右一是换的步骤,按照1.23.写出来,防止变量丢失,所以按照1,2,3反过来写程序
var swapPairs = function(head) {
let ret = new ListNode(0,head), temp = ret
// 循环条件直接考虑末端节点
while(temp.next != null && temp.next.next != null){
let cur = temp.next.next
let pre = temp.next
pre.next = cur.next
cur.next = pre
temp.next = cur
temp = pre
}
return ret.next
};
leetcode19
搞个双指针,fast根据倒数第n个,先跑n个距离,然后slow和fast同时往后走,当fast指向null时,slow就是倒数第n个节点
var removeNthFromEnd = function(head, n) {
let ret = new ListNode(0,head)
let slow = fast = ret
while(n--) fast = fast.next
while(fast.next != null) {
fast = fast.next
slow = slow.next
}
slow.next = slow.next.next
return ret.next
};
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at ‘8’
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。
var getListLen = function(head) {
let len = 0, cur = head
while(cur){
len++
cur = cur.next
}
return len
}
var getIntersectionNode = function(headA, headB) {
let curA = headA, curB = headB
let lenA = getListLen(headA)
let lenB = getListLen(headB)
if(lenA < lenB){
let temp = curA
curA = curB
curB = temp
let lentemp = lenA
lenA = lenB
lenB = lentemp
}
let i = lenA - lenB
while(i-- > 0){
curA = curA.next
}
while(curA && curA !== curB){
curA = curA.next
curB = curB.next
}
return curA
};
leetcode 142
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点
var detectCycle = function(head) {
if(!head || !head.next) return null
let slow = head, fast = head
while(fast.next != null && fast.next.next != null){
fast = fast.next.next
slow = slow.next
if(fast == slow){
let index1 = fast
let index2 = head
while(index1 != index2){
index1 = index1.next
index2 = index2.next
}
return index1
}
}
return null
};
tips
说一个比较难想象的点,快慢指针相遇后的while怎么实现找到入口,很简单特值法,只转1圈就快慢相遇,公式推导里面就有个结论是 : 从head出发到入口的距离 等于 快慢指针相遇点到入口的距离