[编程题] 借用栈实现链表反转

链表反转

题目描述

定义一个函数,输入一个链表的头节点,反转该链表并输出反转后链表的头节点。

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

猜你喜欢

转载自www.cnblogs.com/jiyongjia/p/13193008.html