题目描述
反转一个单链表。
输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL
递归实现
其实拿到这个题目首先应该想到的是递归拆分。
步骤解析
1、既然是反转链表,那我们先从最简单的两个节点开始
2、拿到这个最简单的链表,我们不难看出。因为2的下一个节点是空,所以反转后,2就是头结点
。所以,我们可以先肆无忌惮的将2的next
属性指向倒数第二个节点,也就是1
3、因为1刚好是原来的头结点,所以反转后1就变成了尾节点
,所以1的next
属性就指向了NULL
4、同理当三个节点的时候也是先变后二,在变前二:
5、规律
我们可以理解成,从头开始两两去找,找到那个指向Null的节点,然后将这个节点和这个节点的上一个节点先进行反转。
将反转后的链表返回,接着在去上层执行
6、小结
概括来说,就是将一个链表不断拆分执行相同的操作,当扫描到最后两个节点的时候就开始两两进行反转。
代码实现
public ListNode reseverNode(ListNode head) {
// 头结点为空返回
if(head == null){
return head;
}
// 头节点的下一个节点为空,表示只有一个节点,也返回
if(head.next == null){
return head;
}
//不断两两递归找到最后两个
ListNode listNode = reseverNode(head.next);
// head.next的next节点是空,所以一定要先反回来指
head.next.next = head;
// 在将头变成尾
head.next = null;
return listNode;
}
迭代实现
反转用迭代的话反而更加方便,也好理解。相当于用一个新的链表,将原来的链表从头开始不断的插入,最后返回新链表,就完成了链表的反转。
步骤
1、准备好原来的链表和一个空节点
2、将头节点指向新的节点newList
然后将newList
指向头节点
head指针指向原先头结点的下一个节点:
3、我们会发现中间号线断了一层,当执行newList指向头节点
的时候,头结点的下一个节点已经被断层了
所以,我们需要一个变量来保持对**head
指向的节点的next
的引用**
此致,大概流程也已经讲述完了。
代码实现
public ListNode reseverNode2(ListNode head) {
// 新链表
ListNode newList = null;
// 临时节点,存放head.next的
ListNode temp = null;
while(head != null){
// temp存放下一个节点
temp = head.next;
// 将头先指向新链表,此时的新链表为空
head.next = newList;
// 再将新链表的头指向头结点
newList = head;
// 旧链表的头指针指向旧链表的下一个元素
head = temp;
}
return newList;
}
小结
对于链表反转,个人觉得迭代的方式比递归要好理解一点。但是递归相对来说也没那么难,只要理解成两两组成,两两替换就好了。
关于链表的话,一定要注意先后的问题,如果说某一个地方移动错了,那么会导致元素就找不到了。所以,对于链表来说,执行的先后顺序非常重要。