前言
链表知识点回顾
反转链表_简单
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL
链表单次遍历,将当前节点指向前一节点。最后监听当前节点是否为null
即可。
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
if(!head || !head.next) return head;
var prev=null;
var cur = head;
while(cur){
var next = cur.next;
cur.next = prev;
prev = cur;
cur = next;
}
return prev;
};**
移除链表元素_简单
删除链表中等于给定值 val 的所有节点。
示例:
输入: 1->2->6->3->4->5->6, val = 6 输出: 1->2->3->4->5
var removeElements = function(head, val) {
if(!head) return null
let resListNode = new ListNode(null)
let prev = resListNode,curr = head
prev.next = head
while(curr){
if(curr.val === val){
prev.next = curr.next
curr = curr.next
}else{
prev = curr
curr= curr.next
}
}
return resListNode.next
};
合并两个有序链表_简单
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。
示例: 输入:1->2->4,1->3->4
输出:1->1->2->3->4->4
递归解法
设定递归终止条件,根据l1和l2两个链表的值大小,决定后续节点,递归实现。
/**
* 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) {
if (!l2) return l1
if (!l1) return l2
if (l1.val < l2.val) {
l1.next = mergeTwoLists(l1.next,l2)
return l1
} else {
l2.next = mergeTwoLists(l1,l2.next)
return l2
}
};
链表遍历
额外声明一个返回链表,对原本两个链表进行遍历,得到的较小值存入返回链表中。最后拼接两个链表中多余的部分。
/**
* 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) {
var pHead = new ListNode(-1)
var node = pHead;
while (l1 && l2) {
if (l1.val <= l2.val) {
node.next = l1;
l1 = l1.next
} else {
node.next = l2;
l2 = l2.next
}
node = node.next;
}
node.next = l1? l1:l2;
return pHead.next;
};
重排链表_中等
给定一个单链表 L:L0→L1→…→Ln-1→Ln ,
将其重新排列后变为: L0→Ln→L1→Ln-1→L2→Ln-2→…
你不能只是单纯的改变节点内部的值,而是需要实际的进行节点交换。
示例 1: 给定链表 1->2->3->4, 重新排列为1->4->2->3.
示例 2: 给定链表 1->2->3->4->5, 重新排列为 1->5->2->4->3.
要将链表这样重排,可以分三个步骤,先将链表重中间位置切断,然后将后方链表反转,经过这样处理后再讲两个链表各自从初始节点相连。
/**
* 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 head;
let [low, rightNode] = [head, head.next]
while (rightNode && rightNode.next) {
[low, rightNode] = [low.next, rightNode.next.next]
}
//第二段链表
rightNode = low.next
//第一段链表
low.next = null
low = head
//反转第二段链表
let pre = null
let cur = rightNode
while (cur) {
let next = cur.next
cur.next = pre
pre = cur
cur = next
}
rightNode = pre
//拼接两段链表
while (rightNode) {
let nextLeft = low.next
let nextRight = rightNode.next
low.next = rightNode
rightNode.next = nextLeft
low = nextLeft
rightNode = nextRight
}
};
两数相加_中等
给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) 输出:7 -> 0 -> 8
原因:342 + 465 = 807
顺序遍历链表,取的当前数位之和与当前进位数值,循环执行,得到结果。
/**
* 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) {
if (!l1) return l2
if (!l2) return l1
var res = new ListNode(null)
var resNode = res
let params = 0 //进位值
let val = 0 //当前层的值
while (l1 || l2) {
let x = l1 ? l1.val : 0
let y = l2 ? l2.val : 0
val = (x + y + params) % 10
params = Math.floor((x + y + params) / 10)
resNode.next = new ListNode(val)
resNode = resNode.next
if (l1) l1 = l1.next
if (l2) l2 = l2.next
}
if (params) {
resNode.next = new ListNode(params)
}
return res.next
};
K个一组反转链表_困难
给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。 k 是一个正整数,它的值小于或等于链表的长度。 如果节点总数不是 k
的整数倍,那么请将最后剩余的节点保持原有顺序。 示例: 给你这个链表:1->2->3->4->5 当 k = 2 时,应当返回:
2->1->4->3->5 当 k = 3 时,应当返回: 3->2->1->4->5 说明: 你的算法只能使用常数的额外空间。
你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。
var reverseKGroup = function (head, k) {
if (!head) return head
let cur = head, amount = 0
//得到每次翻转的首位
while (cur !== null && amount !== k) {
cur = cur.next
amount++
}
if (amount === k) {
//递归得到,翻转的连接节点
cur = reverseKGroup(cur, k)
while (k > 0) {
let next = head.next
head.next = cur
cur = head
head = next
k--
}
//防止最后仅剩一位的特殊情况。
head = cur
}
return head
};