前端算法(25)

48 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

题目

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

k 是一个正整数,它的值小于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序。

你不能只是单纯的改变节点内部的值,而是需要实际进行节点交换。

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

题目解析

思路一

首先判断传入的链表的长度是否大于等于k,如果不是,则返回原始链表, 满足第一个条件的时候,通过三个指针prev、curr、next,分别代表上一个指针、当前指针、下一个指针,我们先将curr指向的下一个节点保存到next,然后将curr的下一个节点指向prev,在将curr与prev的指针往后移动一步,重复前面三个步骤直到k循环次数结束,最后我们可以发现prev始终都是传入链表的表头,curr指向下一个要处理的部分,传入的head就是链表的表尾;curr就是新一组需要处理的链表的表头,再将传入的head指向递归处理的结果,将处理的链表连接起来即可。

var reverseKGroup = function(head, k) {
    var idx = 0
    var copyHead = head
    while (copyHead !== null && idx < k) {
        copyHead = copyHead.next
        idx++
    }
    if (idx < k) {
        return head
    }
    var curr = head
    var prev = null
    var n = k
    while (curr !== null && n-- > 0) {
        var next = curr.next
        curr.next = prev
        prev = curr
        curr = next
    }
    head.next = reverseKGroup(curr, k)
    return prev
};

思路二

我们使用递归实现一下,这里可以将链表看成一段一段的执行栈,在此寻找找递归的结束和递归的时机

var reverseKGroup = function(head, k) {
    //用于进行链表转换
    let pre = null,cur = head;
    let p = head;
    //查找长度是否满足反转的数量
    for(let i = 0;i<k;i++){
        if(p == null) return head;
        p = p.next;
    }
    //对该k个链表元素进行反转
    for(let j = 0;j<k;j++){
        let temp = cur.next;
        cur.next = pre;
        pre = cur;
        cur = temp;
    }
    //反转后,head.next已经成为当前反转后链表的最后一个元素,它的指向将是下一个递归的开始点
    //而此时pre已经是最后一个元素,cur是下一个范围的第一元素
    head.next = reverseKGroup(cur,k);
    return pre;
};