Node.java:

package com.me.node;

/**
 * 组成链表的结点对象
 * @author wuyizuokan
 *
 * @param <T>
 */
public class Node<T> {
    /*节点中存放的值*/
    private T value;
    /*下一个节点的引用*/
    private Node<T> next;
    
    public T getValue() {
        return value;
    }
    public void setValue(T value) {
        this.value = value;
    }
    public Node<T> getNext() {
        return next;
    }
    public void setNext(Node<T> next) {
        this.next = next;
    }
}

NodeList.java:

package com.me.node;

/**
 * 链表实现类
 * @author wuyizuokan
 *
 * @param <T>
 */
public class NodeList<T> {
    
    /*链表头节点*/
    private Node<T> head;
    
    /**
     * 向链表添加元素
     * @param t
     */
    public void add(T t) {
        Node<T> node = new Node<T>();
        node.setValue(t);
        if (head == null) {
            head = node;
        } else {
            add(head, node);
        }
    }
    
    private void add(Node<T> node, Node<T> newNode) {
        if (node.getNext() == null) {
            node.setNext(newNode);
        } else {
            add(node.getNext(), newNode);
        }
    }
    
    /**
     * 根据分组反转链表
     * @param i
     */
    public void reverseGroup(int groupSize) {
        head = reverseGroup(head, groupSize);
    }
    
    private Node<T> reverseGroup(Node<T> node, int i) {
        // splitNode用于取数组的前i个元素,下面的for循环会让splitNode移动到第i个节点的位置
        Node<T> splitNode = node;
        for (int j = 1; j < i; j++) {
            if (splitNode != null) {
                splitNode = splitNode.getNext();
            } else {
                break;
            }
        }
        // 如果移动到第i个节点的位置后,节点为null,说明无法达到一组的大小,则反转后直接返回
        if (splitNode == null) {
            return reversList(node);
        }
        // 标记好剩下的链表头,用于下一批分组
        Node<T> nextListHead = splitNode.getNext();
        // 设置splitNode的下一个节点为null,是为了把第i个节点前的链表抽取出来。
        splitNode.setNext(null);
        // 调用反转链表的方法进行反转。
        Node<T> newHead = reversList(node);
        // 递归调用按组反转数组的方法
        Node<T> nextListHeadTmp = reverseGroup(nextListHead, i);
        // 把下一次返回的反转的子列表拼接到这一次后面。
        node.setNext(nextListHeadTmp);
        // 返回新列表的头节点。
        return newHead;
    }
    
    /**
     * 反转列表
     */
    public void reversList() {
        head = reversList(head);
    }
    
    private Node<T> reversList(Node<T> node) {
        // 这里作为递归的出口,相当于是用递归把链表按节点拆分,直到拆分到最后一个节点
        if (node == null || node.getNext() == null) {
            return node;
        }
        
        // 递归调用反转列表的方法,返回新列表的头部
        Node<T> result = reversList(node.getNext());
        // 因为是递归,这里的node实际上是从倒数第二个节点开始往前的每一个节点。需要把它的下一个
        // 节点的下一个节点指向它自己。
        node.getNext().setNext(node);
        // 把自己的下一个节点置空,实际上整个函数执行完了之后,除了之前的头节点的下一个节点引用会为空外,其他节点不会。
        node.setNext(null);
        return result;
    }
    
    public void showList() {
        System.out.print("[");
        if (head != null) {
            showNode(head);
        }
        System.out.println("]");
    }
    
    public void showNode(Node<T> node) {
        if (node != null) {
            System.out.print(node.getValue());
            if (node.getNext() != null) {
                System.out.print(", ");
                showNode(node.getNext());
            }
        }
    }
}

测试代码:

package com.me.reverseLinkedList;

import com.me.node.NodeList;

public class Test {
    public static void main(String[] args) {
        NodeList<String> nodeList = new NodeList<String>();
        nodeList.showList();
        nodeList.add("a");
        nodeList.add("b");
        nodeList.add("c");
        nodeList.add("d");
        nodeList.add("e");
        nodeList.add("f");
        nodeList.add("g");
        nodeList.add("h");
        
        nodeList.showList();
        // 反转链表
        nodeList.reversList();
        nodeList.showList();
        // 分组反转链表
        nodeList.reverseGroup(3);
        nodeList.showList();
    }
}

运行效果:
1236645201911301545479061953485938.png

Q.E.D.