JavaScript链表刷题(三)

216 阅读4分钟

这是我参与8月更文挑战的第24天,活动详情查看:8月更文挑战

之前写了JavaScript链表刷题JavaScript链表刷题(二)

有兴趣的童鞋可以冲,接下来继续刷两道链表题~~

一、反转链表II(指定位置反转)

92. 反转链表 II

给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。  

示例 1:

image.png

  • 输入:head = [1,2,3,4,5], left = 2, right = 4
  • 输出:[1,4,3,2,5]

示例 2:

  • 输入:head = [5], left = 1, right = 1

  • 输出:[5]   提示:

  • 链表中节点数目为 n

  • 1 <= n <= 500

  • -500 <= Node.val <= 500

  • 1 <= left <= right <= n  

进阶: 你可以使用一趟扫描完成反转吗?

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/re… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

将部分链表进行反转,反转后再将头和尾与原来断开的节点连起来。

代码实现 

/**
 * 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} left
 * @param {number} right
 * @return {ListNode}
 */
// 翻转链表
var reverse = function(head, length) {
    let pre = null;
    let cur = head;
    while(length -- ) {
        let next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next;
    }
    head.next = cur;
    return pre;
}
var reverseBetween = function(head, left, right) {
    // 需要翻转的链表长度
    let length = right - left + 1;
    // 设置一个空的子结点(当后面要用到.next时,这里就要new ListNode,否则可用null),放在链表前面,
    // 当翻转链表的left为1时,用pre.next接收翻转后的链表才不会报错
    let ret = new ListNode(-1, head)
    let pre = ret;
    let cur = head;
    // 找到翻转前的节点
    while(-- left) {
        pre = cur;
        cur = cur.next;
    }
    // 翻转链表后将pre.next指向翻转后的链表头
    pre.next = reverse(cur, length);
    return ret.next;
};

二、K个一组反转链表

25. K 个一组翻转链表

给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。

k 是一个正整数,它的值小于或等于链表的长度。

如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

进阶:

  • 你可以设计一个只使用常数额外空间的算法来解决此问题吗?
  • 你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。  

示例 1:

image.png

  • 输入:head = [1,2,3,4,5], k = 2
  • 输出:[2,1,4,3,5]

示例 2:

image.png

  • 输入:head = [1,2,3,4,5], k = 3
  • 输出:[3,2,1,4,5]

示例 3:

  • 输入:head = [1,2,3,4,5], k = 1
  • 输出:[1,2,3,4,5]

示例 4:

  • 输入:head = [1], k = 1
  • 输出:[1]

提示:

  • 列表中节点的数量在范围 sz 内
  • 1 <= sz <= 5000
  • 0 <= Node.val <= 1000
  • 1 <= k <= sz

来源:力扣(LeetCode) 链接:leetcode-cn.com/problems/re… 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路

判断有没有K个节点组成一组,如果有,则对K个节点进行反转,将指针移动到最后一个节点,再进行递归判断;若没有,则返回整个链表。

代码实现 


/**
 * 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) {
    if(head == null) return null;
    // 创建虚拟哨兵节点房在第一个节点前面
    let ret = new ListNode(-1, head);
    let pre = ret;
    return reverseRecursion(ret, pre, k)
};
 
var reverseRecursion= function(ret, pre, k) {
    let tail = pre;
    // 判断是否有K个节点能组成一组
    for(var i = 0; i < k; i++) {
        if(tail && tail.next != null) {
            tail = tail.next;
        } else {
            tail = null;
            return  ret.next;
        }
    }
    // 如果有K个节点,则反转这K个节点,并将指针移到最后一个节点,当做下个k组的前一个节点,递归操作直到剩余的节点不能组成一组
    if(tail != null) {
        pre && (pre.next = reverse(pre.next, k));
        for(var i = 0; i < k; i++) {
            pre && (pre = pre.next);
        }
        return reverseRecursion(ret, pre, k)
    }
}
// k个节点进行反转
var reverse = function(reverseHead, length) {
    let pre = new ListNode(-1, reverseHead);
    let cur = reverseHead;
    while(cur && length--) {
        let next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next;
    }
    reverseHead && (reverseHead.next = cur);
    return pre;
}

系列文章

以下是JavaScript链表刷题的系列文章, 有兴趣的童鞋可以冲~~

JavaScript链表刷题

JavaScript链表刷题(二)

JavaScript链表刷题(三)

JavaScript链表刷题(四)

JavaScript链表刷题(五)