概要
本篇介绍一下关于链表结构很基础的知识,单链表反转。这个知识点同样经常会被各大公司当作面算题考察算法入门,正巧在最近开源的面试题项目中也看见了。事实上跟上一篇LeetCode进阶226-翻转二叉树(华为面试题)同属于如果不理解则会被面试官鄙视系列。
华为面试题-将单向链表reverse,如ABCD变成DCBA,只能搜索链表一次。
原题
206. Reverse Linked List (Easy)
IReverse a singly linked list.
Example:
Input: 1->2->3->4->5->NULL Output: 5->4->3->2->1->NULL Follow up:
A linked list can be reversed either iteratively or recursively. Could you implement both?
206. 反转链表。 (简单)
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL 输出: 5->4->3->2->1->NULL 进阶: 你能否使用循环和递归两种方法解这道题?
- 分类:链表(Linked List)
分析
只搜素一次,即一次循环时间复杂度O(n)。
思路设计
根据要求,反转链表的本质思想是将每个链表节点的next指针指向前一个节点。
方法一:递归
递归思想的核心是是将一件事情拆分递归的“大”事情和实际操作的“小”事情。本题可以宏观上想象,把头节的下一个节点当成一个新的链表(可以简单的理解为将一个链表分成头节点和另一个“大”节点,如下图所示),这样就拆分成了三件事情1、处理“大”节点(新链表),这个链表递归调用进行反转;2、“大”节点的指针逆序指向头节点;3、头节点本身的指针逆向。

1、头节点的判空处理
2、声明bigNode赋值为头节点的下一个节点即head.next;
3、递归逆序处理“大”节点(除头节点以外的链表);
4、将“大”节点(除头节点以外的链表)的指针指向前一个节点即头节点;
5、头节点的指针逆序处理指向空(因为逆序后头节点成了尾节点);
6、返回“大”节点即逆序后的新链表;
方法二:循环(非递归)
每次循环时,将当前节点的next节点指向前一个节点的pre节点,循环过程需要保存记录前一个节点。第一个节点由于反转后变成新链表的最后一个节点因此第一个节点的前一个节点为空。
伪代码:
1、声明变量preNode存储前一个节点;
2、while循环直到达到链表最后一个节点;
i.声明变量temp存储当前节点的next节点;
ii.当前节点指向前一个节点;
iii.单次循环后更新preNode为当前节点;
iiii.head值更新,单次循环后移动head指针到它的next节点;
3.循环结束,返回最后一次preNode赋值为尾节点即逆序后链表的头节点;
编码实践
递归实现
public ListNode reverseList(ListNode head) {
if(head == null || head.next == null) {
return head;
}
ListNode bigNode = head.next;
ListNode node = reverseList(bigNode);
bigNode.next = head;
head.next = null;
return node;
}

循环实现
public ListNode reverseList(ListNode head) {
ListNode preNode = null;
while(head != null){
ListNode temp = head.next;
head.next = preNode;
preNode = head;
head = temp ;
}
return preNode;
}

结语
华为面试题中的链表是一道链表相关的基础知识题,核心考察的是对链表节点指针的理解。最后如果觉得本篇对你有所帮助,给个赞吧~
