【java编程(在线笔试)】两道k个一组翻转链表题目(包含非递归和递归两种解法)

一、给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点也翻转顺序
1. 非递归解法
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        if(head==null||head.next==null||k==1)return head;
        //定义3个变量,t是尾巴,h是正在处理的节点,hh是h的探测器
        ListNode t=null,h=head,hh=head.next;
        int i=1;
        while(true){
            //第i个节点被处理
            h.next=t;
            if(i==k)break; //反转够了k个节点,退出循环
            if(hh==null)break; //hh为空说明h为最后一个节点,已处理完最后一个节点,退出循环
            i++;
            //准备处理第i+1个节点,火车向前开
            t=h;
            h=hh;
            hh=hh.next;
        } 
        if(hh!=null)head.next=reverseKGroup(hh,k);
        return h;
    }

}

2. 递归解法
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        if(head==null||head.next==null||k==1)return head;
        //寻找第k个节点
        ListNode kNode=head;
        for(int i=1;kNode!=null&&i<k;i++){
            kNode=kNode.next;
        }
        //寻找第k+1个节点
        if(kNode!=null){
            kNode=kNode.next;
        }
        //如果够k个节点,则翻转前k个节点
        ListNode res=reverse(head,k);
        if(kNode==null)head.next=null;
        else head.next=reverseKGroup(kNode,k);
        return res;
    }

    ListNode reverse(ListNode head, int k){
        if(head==null||head.next==null||k<=1)return head;
        ListNode res=reverse(head.next,k-1);
        head.next.next=head;
        head.next=null;
        return res;
    }
}
二、给你一个链表,每 k 个节点一组进行翻转,请你返回翻转后的链表。如果节点总数不是 k 的整数倍,那么请将最后剩余的节点保持原有顺序

对应leetcode题目:25. K 个一组翻转链表

1. 非递归解法
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        if(head==null||head.next==null||k==1)return head;
        if(!hasKLength(head,k))return head;
        //定义3个变量,t是尾巴,h是正在处理的节点,hh是h的探测器
        ListNode t=null,h=head,hh=head.next;
        int i=1;
        while(true){
            //第i个节点被处理
            h.next=t;
            if(i==k)break; //反转够了k个节点,退出循环
            if(hh==null)break; //hh为空说明h为最后一个节点,已处理完最后一个节点,退出循环
            i++;
            //准备处理第i+1个节点,火车向前开
            t=h;
            h=hh;
            hh=hh.next;
        } 
        if(hh!=null)head.next=reverseKGroup(hh,k);
        return h;
    }

    boolean hasKLength(ListNode head, int k){
        for(int i=0;i<k;i++){
            if(head==null)return false;
            head=head.next;
        }
        return true;
    }
}

2. 递归解法
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        if(head==null||head.next==null||k==1)return head;
        //寻找第k个节点
        ListNode kNode=head;
        for(int i=1;kNode!=null&&i<k;i++){
            kNode=kNode.next;
        }
        //如果不够k个节点,则不用翻转直接返回head
        if(kNode==null){
            return head;
        }
        //如果够k个节点,则翻转前k个节点
        //先把第k+1个节点记录下来
        kNode=kNode.next;
        ListNode res=reverse(head,k);
        head.next=reverseKGroup(kNode,k);
        return res;
    }

    ListNode reverse(ListNode head, int k){
        if(head==null||head.next==null||k<=1)return head;
        ListNode res=reverse(head.next,k-1);
        head.next.next=head;
        head.next=null;
        return res;
    }
}
}

三、总结

非递归解法的难度是:手动翻转前k个节点。
递归解法的难度是:要在“翻转前k个节点”之前,提交记录下第k+1个节点。不然等“翻转前k个节点”之后,第k个节点指向了第k-1个节点,第k+1个节点就丢了。

你可能感兴趣的:(Java,算法)