445. 两数相加 II
【题目:】 给你两个 非空 链表来代表两个非负整数。数字最高位位于链表开始位置。它们的每个节点只存储一位数字。将这两数相加会返回一个新的链表。
你可以假设除了数字 0 之外,这两个数字都不会以零开头。
【示例 1:】
输入: l1 = [7,2,4,3], l2 = [5,6,4]
输出: [7,8,0,7]
示例2:
输入: l1 = [2,4,3], l2 = [5,6,4]
输出: [8,0,7]
示例3:
输入: l1 = [0], l2 = [0]
输出: [0]
提示:
- 链表的长度范围为
[1, 100] 0 <= node.val <= 9- 输入数据保证链表代表的数字无前导 0
【题解:】 计算两个链表形式的数组之和,我们是需要从链表尾部开始计算的,因此可以有以下思路:
- 反转两个初始链表 l1 => rl1、l2 => rl2
- 在反转链表的同时获取两个链表的长度level1、level2,两个链表长度不一定相同,因此循环次数为最长链表的长度
- 计算的和值newListNode可保存在一个新链表,初始值为0,next为level1、level2同级值的和的个位
- 计算和值需要需要将level1、level2从链表开始处开始逐级计算,并向下一级进行进位计算,最后一级为默认值0
- 将得到的newListNode进行反转,并去除首位的0,得到最终解
【代码:】
/**
* Definition for singly-linked list.
* class ListNode {
* val: number
* next: ListNode | null
* constructor(val?: number, next?: ListNode | null) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
* }
*/
function addTwoNumbers(l1: ListNode | null, l2: ListNode | null): ListNode | null {
let {level: level1, head: rl1} = reserve(l1)
let {level: level2, head: rl2} = reserve(l2)
let level: number = Math.max(level1, level2)
let newListNode: ListNode = new ListNode(0, null), cur:ListNode = newListNode
while(level){
let val1: number = rl1 && rl1.val || 0
let val2: number = rl2 && rl2.val || 0
let nVal: number = cur.val || 0
let n1: number = (nVal + val1 + val2) % 10
let n2: number = Math.floor((nVal + val1 + val2) / 10)
cur.val = n1
cur.next = new ListNode(n2, null)
cur = cur.next
rl1 = (rl1 && rl1.next) || null
rl2 = (rl2 && rl2.next) || null
level--
}
let {head: ret} = reserve(newListNode)
if(ret.val === 0) ret = ret.next
return ret
};
function reserve(head: ListNode): {level: number, head: ListNode | null}{
if(!head) return {level: 0, head: null}
let pre = null, cur: ListNode = head, con = 0
while(cur){
let next: ListNode | null = cur.next
cur.next = pre
pre = cur
cur = next
con++
}
return {level: con, head: pre}
}
剑指 Offer 35. 复杂链表的复制
【题目:】 请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。
【示例 1:】
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
【示例2:】
输入: head = [[1,1],[2,1]]
输出: [[1,1],[2,1]]
【示例3:】
输入: head = [[3,null],[3,0],[3,null]]
输出: [[3,null],[3,0],[3,null]]
【示例 4:】
输入: head = []
输出: []
解释: 给定的链表为空(空指针),因此返回 null。
提示:
-10000 <= Node.val <= 10000Node.random为空(null)或指向链表中的节点。- 节点数目不超过 1000 。
【题解:】 基本思路:
-
遍历整个链表,复制每个节点及其值,然后拼接到原节点的后面,形成一个新的链表
x=>y=>z==>x=>x1=>y=>y1=>z=>z1 -
找到一个克隆节点,修正random,将克隆节点的random指向克隆节点,
克隆节点的random为原节点的random的next -
拆分链表分成原链表和克隆链表
【代码:】
/**
* // Definition for a Node.
* function Node(val, next, random) {
* this.val = val;
* this.next = next;
* this.random = random;
* };
*/
/**
* @param {Node} head
* @return {Node}
*/
var copyRandomList = function(head) {
if(!head) return null
// 创建两个指针
let cur = head, cur1
// 遍历整个链表,复制每个节点及其值,然后拼接到原节点的后面
while(cur){
cur1 = new Node(cur.val, cur.next, cur.random)
cur.next = cur1
cur = cur1.next
}
// 找到一个克隆节点,修正random,将克隆节点的random指向克隆节点
cur = head.next
while(cur){
cur.random && (cur.random = cur.random.next)
cur = cur.next && cur.next.next
}
// 拆分链表分成原链表和克隆链表
cur = cur1 = head.next
while(cur1.next){
head.next = head.next.next
cur1.next = cur1.next.next
head = head.next
cur1 = cur1.next
}
head.next = null
return cur
};