文章目录 36 两数相加 37 删除链表的倒数第n个节点 38 两两交换链表中的节点 39 k个一组翻转链表 40 随机链表的复制
36 两数相加
创建一个新的链表(哨兵节点指向),这个链表用来表示两个数相加后的和。 从个位开始相加,每次都向新链表尾部添加一个节点,即保存一个数位。 遍历l1和l2,每次都计算sum = l1.val + l2.val + carry(进位),将sum % 10作为当前节点要保存的数位,将sum / 10作为新的进位值。
javascript">
var addTwoNumbers = function ( l1, l2 ) { var carry = 0 ; var dummy = new ListNode ( ) ; cur = dummy; while ( l1 || l2 || carry) { sum = ( l1? l1. val: 0 ) + ( l2? l2. val: 0 ) + carry; var node = new ListNode ( sum % 10 ) ; cur. next = node; carry = Math. floor ( sum / 10 ) ; cur = cur. next; if ( l1) { l1 = l1. next; } if ( l2) { l2 = l2. next; } } return dummy. next;
} ;
37 删除链表的倒数第n个节点
快慢指针 添加哨兵节点,要删除倒数第n个节点,需要先找到倒数第n + 1个节点(即第n个节点的前一个结点)。 快指针先移动n + 1步,然后快、慢指针一起向前移动,当快指针指向null时,慢指针就指向倒数第n + 1个节点。 快指针比慢指针快n + 1步,所以当快指针指向null时,慢指针距离null还有n + 1个节点,即慢指针指向倒数第n + 1个节点。 将倒数第n + 1个节点指向倒数第n - 1个节点。
javascript">
var removeNthFromEnd = function ( head, n ) { var dummy = new ListNode ( ) ; dummy. next = head; var fast = dummy, slow = dummy; while ( n + 1 && fast != null ) { fast = fast. next; n-- ; } while ( fast != null ) { fast = fast. next; slow = slow. next; } slow. next = slow. next. next; return dummy. next;
} ;
38 两两交换链表中的节点
添加哨兵节点。 操作指针cur指向要反转的两个节点的前一个结点,例如要反转节点3、4,cur应该指向节点2。 当结点个数为偶数时,cur.next = null结束操作。 当结点个数为奇数时,cur.next.next = null结束操作。 例:哨兵节点(cur) => 节点1 => 节点2 => 节点3 => 节点4 => … => null,这里要反转节点1、2。 临时变量:temp1存储节点2,temp2存储节点3。 ① cur指向节点2。 ② 节点2指向节点1(temp1)。 ③ 节点1指向节点3(temp2)。 改变顺序后的链表为:哨兵节点(cur) => 节点2 => 节点1 => 节点3 => 节点4 => … => null。 操作节点cur指向节点1,继续进行节点3、4的交换。
javascript">
var swapPairs = function ( head ) { var dummy = new ListNode ( ) ; dummy. next = head; var cur = dummy; while ( cur. next != null && cur. next. next != null ) { var temp1 = cur. next; var temp2 = cur. next. next. next; cur. next = cur. next. next; cur. next. next = temp1; cur. next. next. next = temp2; cur = cur. next. next; } return dummy. next;
} ;
39 k个一组翻转链表
先求链表长度,每次判断剩余节点个数 >= k才能进行反转。 将连续k个节点反转:反转结束后,从原来的链表上看,pre指向这k个节点的最后一个节点,cur指向这k个节点的下一个节点。反转链表的解析及代码详见:31 反转链表。 添加哨兵节点,p指向哨兵节点,p作为这k个反转节点的前一个结点,该节点在反转后.next指向pre(反转后的第一个节点)。 临时变量pn作为p结点的下一个结点,同时pn也是这k个节点在反转前的第一个节点、反转后的最后一个结点,pn(下一段的前一个节点)在反转结束后.next指向cur(下一段的第一个节点)。 更新p,指向pn。
javascript">
var reverseKGroup = function ( head, k ) { var count = 0 ; var cur = head; while ( cur) { count++ ; cur = cur. next; } var dummy = new ListNode ( ) ; dummy. next = head; var p = dummy; var pre = null ; cur = p. next; while ( count >= k) { count -= k; for ( var i = 1 ; i <= k; i++ ) { var temp = cur. next; cur. next = pre; pre = cur; cur = temp; } var pn = p. next; p. next = pre; pn. next = cur; p = pn; } return dummy. next;
} ;
40 随机链表的复制
哈希表 构造原链表节点和新链表节点的映射关系,然后根据原链表节点的next和random指向,更新新链表。 第1次遍历链表:新建节点,在哈希表中添加键值对(原节点,新节点)。 第2次遍历链表:添加新节点的next和random指向。 注意:若节点的.next或.random为null,map.get(null)返回undefined,undefined的布尔值为false。
javascript">
var copyRandomList = function ( head ) { if ( head == null ) { return head; } var map = new Map ( ) ; var cur = head; while ( cur) { map. set ( cur, new _Node ( cur. val) ) ; cur = cur. next; } cur = head; while ( cur) { map. get ( cur) . next = map. get ( cur. next) || null ; map. get ( cur) . random = map. get ( cur. random) || null ; cur = cur. next; } return map. get ( head) ;
} ;