【JavaScript】LeetCode:36-40

文章目录

  • [36 两数相加](#36 两数相加)
  • [37 删除链表的倒数第n个节点](#37 删除链表的倒数第n个节点)
  • [38 两两交换链表中的节点](#38 两两交换链表中的节点)
  • [39 k个一组翻转链表](#39 k个一组翻转链表)
  • [40 随机链表的复制](#40 随机链表的复制)

36 两数相加

  • 创建一个新的链表(哨兵节点指向),这个链表用来表示两个数相加后的和。
  • 从个位开始相加,每次都向新链表尾部添加一个节点,即保存一个数位。
  • 遍历l1和l2,每次都计算sum = l1.val + l2.val + carry(进位),将sum % 10作为当前节点要保存的数位,将sum / 10作为新的进位值。
javascript 复制代码
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} l1
 * @param {ListNode} l2
 * @return {ListNode}
 */
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 复制代码
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} n
 * @return {ListNode}
 */
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 复制代码
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @return {ListNode}
 */
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; // dummy => 2
        cur.next.next = temp1; // 2 => 1
        cur.next.next.next = temp2; // 1 => 3
        cur = cur.next.next; // cur => 1
    }
    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 复制代码
/**
 * Definition for singly-linked list.
 * function ListNode(val, next) {
 *     this.val = (val===undefined ? 0 : val)
 *     this.next = (next===undefined ? null : next)
 * }
 */
/**
 * @param {ListNode} head
 * @param {number} k
 * @return {ListNode}
 */
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 复制代码
/**
 * // 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 == 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);
};
相关推荐
高飞的Leo9 分钟前
工厂方法模式
java·开发语言·工厂方法模式
菜鸡中的奋斗鸡→挣扎鸡14 分钟前
c++ count方法
开发语言·c++
DT——23 分钟前
Vue2和Vue3的区别
开发语言·javascript·vue.js
cliff,32 分钟前
JavaScript基础巩固之小游戏练习
javascript·笔记·学习
知识分享小能手1 小时前
CSS3学习教程,从入门到精通,CSS3 定位布局页面知识点及案例代码(18)
前端·javascript·css·学习·html·css3·html5
程序员总部1 小时前
单例模式在Python中的实现和应用
开发语言·python·单例模式
demonlg01121 小时前
Go 语言 fmt 模块的完整方法详解及示例
开发语言·后端·golang
Python私教1 小时前
Vue 在现代 Web 开发中的优势
前端·javascript·vue.js
Front_Yue1 小时前
Unity 与 JavaScript 的通信交互:实现跨平台的双向通信
javascript·3d·unity
fridayCodeFly1 小时前
<KeepAlive>和<keep-alive>有什么区别
前端·javascript·vue.js