[編程題] 借用棧實現鏈表反轉


鏈表反轉

題目描述

定義一個函數,輸入一個鏈表的頭節點,反轉該鏈表並輸出反轉后鏈表的頭節點。

image-20200625211648166

思考分析(遞歸思想)

我們可以借助棧結果,把鏈表存入棧中的時候,再次拿出來的時候就是逆序的了。但是要注意其中關鍵一步,取出的時候要消除每個節點的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;
    }
}

測試:

image-20200625211923581

解釋出棧的時候 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);
    }
}

可以看到正常輸出反轉:

image-20200625212125270

我們打印出如果不同消除的話,節點的指向關系:

修改代碼如下進行驗證

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;
}

輸出:

(我們發現節點的指向還是正向的)

image-20200625212340255


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM