描述
给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。
数据范围: 0≤n≤1000
要求:空间复杂度 O(1)O(1) ,时间复杂度 O(n)O(n) 。
如当输入链表{1,2,3}时,
经反转后,原链表变为{3,2,1},所以对应的输出为{3,2,1}。
以上转换过程如下图所示:
示例1
输入:{1,2,3}
返回值:{3,2,1}
示例2
输入:{}
返回值:{}
说明:空链表则输出空
解决方案
1,双链表求解
双链表求解是把原链表的结点一个个摘掉,每次摘掉的链表都让他成为新的链表的头结点,然后更新新链表
他每次访问的原链表节点都会成为新链表的头结点,最后再来看下代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| public ListNode ReverseList(ListNode head) { ListNode newHead = null; while (head != null) { ListNode temp = head.next; head.next = newHead; newHead = head; head = temp; } return newHead; }
|
2,使用栈解决
链表的反转是老生常谈的一个问题了,同时也是面试中常考的一道题。最简单的一种方式就是使用栈,因为栈是先进后出的。实现原理就是把链表节点一个个入栈,当全部入栈完之后再一个个出栈,出栈的时候在把出栈的结点串成一个新的链表。原理如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| import java.util.Stack;
public class Solution { 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; } node.next = null; return dummy; } }
|
3,递归解决
我们再来回顾一下递归的模板,终止条件,递归调用,逻辑处理。
1 2 3 4 5 6 7 8 9 10 11
| public ListNode reverseList(参数0) { if (终止条件) return;
逻辑处理(可能有,也可能没有,具体问题具体分析)
ListNode reverse = reverseList(参数1);
逻辑处理(可能有,也可能没有,具体问题具体分析) }
|
终止条件就是链表为空,或者是链表没有尾结点的时候,直接返回
1
| if` `(head == ``null` `|| head.next == ``null``)`` ``return` `head
|
递归调用是要从当前节点的下一个结点开始递归。逻辑处理这块是要把当前节点挂到递归之后的链表的末尾,看下代码
1 2 3 4 5 6 7 8 9 10 11 12
| public ListNode ReverseList(ListNode head){ return reverseListInt(head,null); }
private ListNode reverseListInt(ListNode head,ListNode newHead){ if(head==null) return newHead; ListNode next=head.next; head.next=newHead; ListNode node=reverseListInt(next,head); return node; }
|