使用javascript实现常用leecode算法---链表篇
前端面试 必备算法
实现链表
class Node {
constructor(val, next) {
this.val = val === undefined ? 0 : val;
this.next = next === undefined ? null : next;
}
}
class LinkedList {
constructor(value) {
this.head = new Node(value);
}
append(val) {
const newNode = new Node(val);
let currentNode = this.head;
while (currentNode.next) {
currentNode = currentNode.next;
}
currentNode.next = newNode;
}
}
var node = new LinkedList();
先后插入4、5、1、9
node.append(4);
node.append(5);
node.append(1);
node.append(9);
const _node = node.head.next;
1.合并两个有序链表
将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
输入:l1 = [1,2,4], l2 = [1,3,4] 输出:[1,1,2,3,4,4]
输入:l1 = [], l2 = [] 输出:[]
var mergeTwo = function(l1, l2){
let node = new Node('1');
let pre = node;
while(l1!==null && l2!==null){
if(l1.val<l2.val){
pre.next = l1;
l1 = l1.next;
}else{
pre.next = l2;
l2 = l2.next;
}
pre = pre.next;
}
pre.next = l1==null?l2:l1;
return node.next;
}
var mergeTwoLists = function(l1, l2){
if(l1==null) return l2;
if(l2==null) return l1;
if(l1.val<l2.val){
l1.next = mergeTwo(l1.next, l2);
return l1;
}else{
l2.next = mergeTwo(l1, l2.next);
return l2;
}
}
2.反转从位置 m 到 n 的链表,其他正常返回
var reverseBetween = function (head, m, n) {
if (head == null || head.next == null || m == n) {
return head;
}
let node = new Node("a", head);
let p0 = node;
for (var i = 0; i < m - 1; i++) {
p0 = p0.next;
}
let pre = null;
let cur = p0.next;
for (var j = 0; j < n - m + 1; j++) {
let next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
p0.next.next = cur;
p0.next = pre;
return node.next;
};
3.k个一组翻转链表
[1,2,3,4,5] k=2 返回:[2,1,4,3,5]
const reverseK = function (head, k) {
var n = 0;
var cur = head;
while (cur !== null) {
n++;
cur = cur.next;
}
var temp = new Node("a", head);
var p0 = temp;
cur = p0.next;
let pre = null;
while (n >= k) {
n = n - k;
for (var i = 0; i < k; i++) {
var next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
x = p0.next;
p0.next.next = cur;
p0.next = pre;
p0 = x;
}
return temp.next;
};
4.返回链表的中间节点 [1,2,3,4,5]返回3 [1,2,3,4,5,6]返回4
const findMiddleNode1 = function (head) {
let fast = head;
let slow = head;
while (fast && fast.next) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
};
5.环形链表 是否有环
const isCircle = function (head) {
let fast = head;
let slow = head;
while (fast && fast.next) {
fast = fast.next.next;
slow = slow.next;
if (fast == slow) {
return true;
}
}
return false;
};
6.环形链表II
输入:head = [3,2,0,-4], pos = 1 输出:返回索引为 1 的链表节点,解释:链表中有一个环,其尾部连接到第二个节点。
var detectCycle = function (head) {
let fast = head;
let slow = head;
while (fast && fast.next) {
fast = fast.next.next;
slow = slow.next;
// 相遇了
if (fast == slow) {
fast = head;
while (fast != slow) {
fast = fast.next;
slow = slow.next;
}
return slow;
}
}
return null;
}
7.删除链表中的节点
head = [4,5,1,9], node = 5 输出:[4,1,9]
const deleteNode = function(head, num){
let node = new Node('1', head);
let cur = node;
while(cur.next != null){
if(cur.next.val == num){
cur.next = cur.next.next;
}
cur = cur.next;
}
return node.next;
}
8.删除链表的倒数第N个节点
输入:head = [1,2,3,4,5,6], n = 2 输出:[1,2,3,4,6]
const removeLastN = function(head, n){
let node = new Node("a", head);
let fast = node;
let slow = node;
while(n>0 && fast!=null){
fast = fast.next;
n--;
}
fast = fast.next;
while(fast!=null){
fast = fast.next;
slow = slow.next;
}
slow.next = slow.next.next;
return node.next;
}
9.删除排序链表中的重复元素
输入:head = [1,1,2] 输出:[1,2] 输入:head = [1,1,2,3,3] 输出:[1,2,3]
const removeDoubleNode = function(head){
if(head==null || head.next==null){
return head;
}
let cur = head;
while(cur && cur.next){
if(cur.next.val===cur.val){
cur.next = cur.next.next;
}else{
cur = cur.next;
}
}
return node.next;
}
10. 删除排序链表中的重复元素 II
给定一个已排序的链表的头 head , 删除原始链表中所有重复数字的节点,只留下不同的数字 。返回 已排序的链表 。 输入:head = [1,2,3,3,4,4,5] 输出:[1,2,5]
const removeDoubleNode1 = function(head){
let node = new Node('1', head);
let cur = node;
while(cur.next && cur.next.next){
if(cur.next.val == cur.next.next.val){
let x = cur.next.val;
while(cur.next && cur.next.val ===x){
cur.next = cur.next.next;
}
}else{
cur = cur.next;
}
}
return node.next;
}
11.重排链表
给定一个单链表 L 的头节点 head ,单链表 L 表示为:L0 → L1 → … → Ln - 1 → Ln请将其重新排列后变为:L0 → Ln → L1 → Ln - 1 → L2 → Ln - 2 → …不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
// 找到中间节点
const findMidNode = function (head) {
let fast = head;
let slow = head;
while (fast && fast.next) {
fast = fast.next.next;
slow = slow.next;
}
return slow;
};
// 反转链表
const reverseNode = function (head) {
let cur = head;
let pre = null;
while (cur !== null) {
let next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
return pre;
};
const reorderList = function (head) {
// 找到中间的节点
let node = findMidNode(head);
// 反转
let p1 = reverseNode(node);
// 拼接
let p0 = head;
while (p1.next !== null) {
let x = p0.next;
let x1 = p1.next;
p0.next = p1;
p1.next = x;
p0 = x;
p1 = x1;
}
};
12.分隔链表
给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 输入:head = [1,4,3,2,5,2], x = 3 输出:[1,2,2,4,3,5] 输入:head = [2,1], x = 2 输出:[1,2]
const partition = function(head, x){
if(head==null || head.next==null){
return head;
}
const less = new Node('a');
const more = new Node('b');
const cur = less;
const cur_1 = more;
while(head!==null){
if(head.val >= x){
more.next = head;
more = more.next;
}else{
less.next = head;
less = less.next;
}
head = head.next;
}
more.next = null;
less.next = cur_1.next;
return cur.next;
}