package linkedlist;
/**
* 反转链表
* 反转一个单链表。
*
* 示例:
*
* 输入: 1->2->3->4->5->NULL
* 输出: 5->4->3->2->1->NULL
* 进阶:
* 你可以迭代或递归地反转链表。你能否用两种方法解决这道题?
*
* 作者:力扣 (LeetCode)
* 链接:https://leetcode-cn.com/leetbook/read/top-interview-questions-easy/xnnhm6/
* 来源:力扣(LeetCode)
* 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*
* */
public class ReverseList {
private static class ListNode {
private int val;
private ListNode next;
ListNode(int val) {
this.val = val;
}
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
public static void main(String[] args) {
ListNode node5 = new ListNode(5);
ListNode node4 = new ListNode(4, node5);
ListNode node3 = new ListNode(3, node4);
ListNode node2 = new ListNode(2, node3);
ListNode node1 = new ListNode(1, node2);
ListNode head = reverseListNode(node1);
while (head.next!=null){
System.out.println("val "+head.val);
head = head.next;
}
System.out.println("val "+head.val);
}
// 1 -> 2 -> 3 -> 4 -> 5
// 1->2 2->1
// 1. stack
// 2. 创建新链表
// 3. 递归写法
// 第一种写法:递归写法
// 不要纠结于这个reverse的过程是怎么发生变化的,我们只需要知道这个最后将原来的链表发生了翻转
// 1 -> 2 < -3 <- 4 <- 5 <- 6
// ↑ ↓ last last指针指向了逆转之后链表的开头 节点6
// head null
// head.next.next = head 就是将 指向2节点的null指针指向 1 节点
// 1 -> 2 < -3 <- 4 <- 5 <- 6
// ↑ ↙ ↓(x) last last 指针指向了逆转之后链表的开头
// head null(x)
// head.next = null 断开节点1指向节点2
// null<- 1 <- 2 < -3 <- 4 <- 5 <- 6
// ↑ ↙ last last 指针指向了逆转之后链表的开头
// head
private static ListNode reverseListNode(ListNode head){
if (head == null ||head.next ==null){
return head;
}
ListNode last = reverseListNode(head.next);
head.next.next = head;
head.next = null;
return last;
}
}
输出结果:
val 5
val 4
val 3
val 2
val 1
思路:可以从简单例子推广到更大范围例子的方式来思考,比如只考虑有两个节点的情况,不如 1->2 这两个节点,反转之后就 2->1,递归调用 reverse 方法,然后判断到 2节点的next 是空,则将2节点作为输出链表的开头,然后将 head.next.next 指向 head, 这里的head.next 就是节点2, 然后将节点2的next指向节点1, 即 head节点,这样就是调整了节点2和节点1的指向顺序。然后 head.next 赋值为空,则将两个节点的链表进行反转处理,其他更多节点的链表也可以尝试这样思考。
第二种解法:
利用 三个指针来处理,cur、next、pre 指针来进行链表的反转操作。
public ListNode reverse(ListNode head){
if (head ==null) {
return null;
}
if (head.next ==null){
return head;
}
ListNode cur = head;
ListNode pre = null;
ListNode next = null;
while (cur!=null){
next = cur.next; //next指向 cur.next 节点
cur.next = pre; //cur.next 指向 pre 节点
pre = cur; //pre 指向 cur 节点
cur = next; //cur 指向 next 节点
}
return pre; //返回反转链表后的首节点
}
参考: