链表反转
题目描述
定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。
思考分析(递归思想)
我们可以借助栈结果,把链表存入栈中的时候,再次拿出来的时候就是逆序的了。但是要注意其中关键一步,取出的时候要消除每个节点的next域的指向(正向存入栈中的每个节点的next域的指向是没变的,比如a的next依然标记了b).最终我们返回从栈中出来的那个链表的head.
Java代码
import java.util.*;
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public ListNode reverseList(ListNode head) {
//借助栈
Deque<ListNode> stack = new LinkedList();
ListNode newHead=null; //返回的逆转栈
//安全验证
if(head==null) return null;
if(head.next==null) return head;
//一个个入栈
while(head!=null){
stack.push(head);
head = head.next;
}
head = stack.pop();
ListNode cur = head;
//出栈
while(!stack.isEmpty()){
ListNode node = stack.pop();
//我们虽然正向存入了栈中,但是每个节点的next的指向还没变,在这里要消除
node.next=null; //这一步关键(//消除正向原本的指向关系)
cur.next = node;
cur = node;
}
return head;
}
}
测试:
解释出栈的时候 node.next=null;代码的作用
(1)我们把完整的案例执行输出
package jianzhioffer;
import java.util.Deque;
import java.util.LinkedList;
import java.util.Stack;
/**
* @author jiyongjia
* @create 2020/6/25 - 20:25
* @descp:
*/
public class P16_reverseLinkedList {
static class Node{
String val;
Node next;
public Node(String val) {
this.val = val;
}
@Override
public String toString() {
return "Node("+this.val+")";
}
}
public static Node reverseLinkedList(Node head){
Stack<Node> stack = new Stack<Node>();
while(head!=null){
stack.push(head);
head = head.next;
}
if(!stack.isEmpty()) {
head = stack.pop();
}
Node cur = head;
System.out.println("反向操作中...");
while(!stack.isEmpty()){
Node node = stack.pop();
/*//验证节点指向的测试代码
System.out.println("node:"+node+"--->>node.Next:"+node.next);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
//我们虽然是存入栈中了,但是它的next值还在,比如a的next还是正向的b;
node.next = null; //消除正向原本的指向关系
cur.next = node;
cur = node;
}
return head;
}
public static void display(Node head){
System.out.print("list:");
Node cur = head;
while(cur!=null){
System.out.print(cur+"->");
cur = cur.next;
}
System.out.println();
}
public static void main(String[] args) {
Node a = new Node("a");
Node b = new Node("b");
Node c = new Node("c");
Node d = new Node("d");
Node e = new Node("e");
Node f = new Node("f");
Node g = new Node("g");
a.next = b;
b.next = c;
c.next = d;
d.next = e;
e.next = f;
f.next = g;
System.out.println("原始链表:");
display(a);
Node head = reverseLinkedList(a);
System.out.println("反转之后的链表:");
display(head);
}
}
可以看到正常输出反转:
我们打印出如果不同消除的话,节点的指向关系:
修改代码如下进行验证
while(!stack.isEmpty()){
Node node = stack.pop();
//打印节点的关系指向
System.out.println("node:"+node+"--->>node.Next:"+node.next);
//睡眠下才能看到效果,不然直接栈溢出
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//我们虽然是存入栈中了,但是它的next值还在,比如a的next还是正向的b;
//node.next = null; //消除正向原本的指向关系
cur.next = node;
cur = node;
}
输出:
(我们发现节点的指向还是正向的)