问题描述
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
限制:
0 <= 节点个数 <= 5000
有三种方案:
使用栈解决
链表反转在面试中经常被问到。使用栈解决,具体流程如下:
代码如下:
public ListNode reverseList(ListNode head) {
Stack<ListNode> stack = new Stack<>();
//把链表节点全部摘掉放到栈中
while (head != null) {
stack.push(head);
head = head.next;
}
if (stack.isEmpty())
return null;
ListNode node = stack.pop();
ListNode dummy = node;
//栈中的结点全部出栈,然后重新连成一个新的链表
while (!stack.isEmpty()) {
ListNode tempNode = stack.pop();
node.next = tempNode;
node = node.next;
}
//最后一个结点就是反转前的头结点,一定要让他的next
//等于空,否则会构成环
node.next = null;
return dummy;
}
双链表解决
使用双链表解决流程如下:
他每次访问的原链表节点都会成为新链表的头结点,最后再来看下代码
public ListNode reverseList(ListNode head) {
//新链表
ListNode newHead = null;
while (head != null) {
//先保存访问的节点的下一个节点,保存起来
//留着下一步访问的
ListNode temp = head.next;
//每次访问的原链表节点都会成为新链表的头结点,
//其实就是把新链表挂到访问的原链表节点的
//后面就行了
head.next = newHead;
//更新新链表
newHead = head;
//重新赋值,继续访问
head = temp;
}
//返回新链表
return newHead;
}
递归解决
递归模板:
public ListNode reverseList(参数0) {
if (终止条件)
return;
逻辑处理(可能有,也可能没有,具体问题具体分析)
//递归调用
ListNode reverse = reverseList(参数1);
逻辑处理(可能有,也可能没有,具体问题具体分析)
}
注意终止条件:链表为空或者链表没有尾结点
if (head == null || head.next == null)
return head;
代码如下:
public ListNode reverseList(ListNode head) {
//终止条件
if (head == null || head.next == null)
return head;
//保存当前节点的下一个结点
ListNode next = head.next;
//从当前节点的下一个结点开始递归调用
ListNode reverse = reverseList(next);
//reverse是反转之后的链表,因为函数reverseList
// 表示的是对链表的反转,所以反转完之后next肯定
// 是链表reverse的尾结点,然后我们再把当前节点
//head挂到next节点的后面就完成了链表的反转。
next.next = head;
//这里head相当于变成了尾结点,尾结点都是为空的,
//否则会构成环
head.next = null;
return reverse;
}
对上面代码进行改进,将head.next.next = head;代码如下:
public ListNode reverseList(ListNode head) {
if (head == null || head.next == null)
return head;
ListNode reverse = reverseList(head.next);
head.next.next = head;
head.next = null;
return reverse;
}