鏈表反轉
題目描述
定義一個函數,輸入一個鏈表的頭節點,反轉該鏈表並輸出反轉后鏈表的頭節點。
思考分析(遞歸思想)
我們可以借助棧結果,把鏈表存入棧中的時候,再次拿出來的時候就是逆序的了。但是要注意其中關鍵一步,取出的時候要消除每個節點的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;
}
輸出:
(我們發現節點的指向還是正向的)