题目 206. 反转链表
反转一个单链表。
示例:
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
简单介绍:
难度:简单
使用语言:JAVA。
这道题来自leetcode题库的链表算法标签。
解题思路:
首先看题、分析题意:
1.如何实现反转链表
既然,我们已经分析出来题目的关键任务了,下面我们就可以开始思考实现了。
我们采用算法与数据结构的思路来剖析一下这题,
数据结构:
要实现对数据的操作,我们要先明确存储数据的数据结构。
1.ListNode - 题目所给的数据结构
算法1 - 利用外部空间
这种方式很简单,先申请一个动态扩容的数组或者容器,比如 ArrayList 这样的。然后不断遍历链表,将链表中的元素添加到这个容器中。再利用容器自身的 API,反转整个容器,这样就达到反转的效果了。最后同时遍历容器和链表,将链表中的值改为容器中的值。这里我就不展示代码了
算法2 - 双指针
1.申请两个指针,第一个指针叫 pre,最初是指向 null 的
2.第二个指针 cur 指向 head,然后不断遍历 cur
3.每次迭代到 cur,都将 cur 的 next 指向 pre,然后 pre 和 cur 前进一位
4.都迭代完了(cur 变成 null 了),pre 就是最后一个节点了
class Solution {
public ListNode reverseList(ListNode head) {
//申请节点,pre和 cur,pre指向null
ListNode pre = null;
ListNode cur = head;
ListNode tmp = null;
while(cur!=null) {
//记录当前节点的下一个节点
tmp = cur.next;
//然后将当前节点指向pre
cur.next = pre;
//pre和cur节点都前进一位
pre = cur;
cur = tmp;
}
return pre;
}
}
算法3 - 递归
递归非常不好理解,所以我们先从它的出口开始着手。
递归的出口:是当前节点或者下一个节点 == null
在函数内部,改变节点的指向,也就是 head 的下一个节点指向 head 递归函数那句
head.next.next = head; //就是 head 的下一个节点指向head。
class Solution {
public ListNode reverseList(ListNode head) {
//递归终止条件是当前为空,或者下一个节点为空
if(head==null || head.next==null) {
return head;
}
//这里的cur就是最后一个节点
ListNode cur = reverseList(head.next);
//如果链表是 1->2->3->4->5,那么此时的cur就是5
//而head是4,head的下一个是5,下下一个是空
//所以head.next.next 就是5->4
head.next.next = head;
//防止链表循环,需要将head.next设置为空
head.next = null;
//每层递归函数都返回cur,也就是最后一个节点
//一旦 cur 确认就是反转链表的头部,所以 return 的一直是 5
return cur;
}
}
算法4 - 普通解法
这种解法就非常普通,利用普通的转换指针指向的方法来反转链表
class Solution {
public ListNode reverseList(ListNode head) {
ListNode new_head = null;
while(head != null){
ListNode nextone = head.next;
head.next = new_head;
new_head = head;
head = nextone;
}
return new_head;
}
}