[面试经典编程题] 2 翻转单链表的四种方法

翻转单链表

题目描述

image-20200713211916471

思路

三个指针,分别n1,n2,n3;三个指针不断往后移动。

image-20200713204850871

Java代码

方法1:三个指针标记循环往后走

 //方法3:三个指针循环后移
    public ListNode reverseList(ListNode head) {
        if(head==null) {return null;}

        ListNode n0 = null;
        ListNode n1 = head;
        ListNode n2 = n1.next;
        while(n1!=null){
            //翻转
            n1.next = n0;

            //三个指针移动
            n0 = n1;
            n1 = n2;
            //在结尾的地方,这里存在为空的情况,需判断
            if(n2!=null){
                n2 = n2.next;
            }
        }
        return n0;//最终结束是返回n1
    }

输出最优:

image-20200713212241591

方法2:头插法

思路:

image-20200713213910782

Java代码:

//方法4:头插法
     public ListNode reverseList(ListNode head) {
         ListNode newHead = null;
         ListNode cur = head;
         while(cur!=null){
            //保存下一个
            ListNode next = cur.next;
            //摘一个下来
            cur.next = newHead;
            newHead = cur;
            //然后取下一个
            cur = next;
         }
         //退出while就是取完了
         return newHead;
     }

效率:

image-20200713214029349

方法3:借助栈

 //方法1:借助栈完成反转
    public ListNode reverseList1(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();

            /*  //探究:验证节点指向的测试代码
            System.out.println("node:"+node+"--->>node.Next:"+node.next);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }*/
            
            //我们虽然正向存入了栈中,但是每个节点的next的指向还没变,在这里要消除
            node.next=null;  //这一步关键(//消除正向原本的指向关系)
            cur.next = node;
            cur = node;
        }

        return head;
    }

方法4:简单递归

//方法2:简单递归
    public ListNode reverseList2(ListNode head) {
        if(head==null) {return null;}
        if (head.next==null) {return head;}
        
        //1 前向遍历得到最后的那个节点,并标记
        ListNode rev = head;
        while (rev.next!=null){
            rev = rev.next;  //即rev标记了最后的节点
        }
        
        //2 我们再次前向遍历,改变指针指向顺序
        ListNode cur=head;
        while (cur.next!=null){
            cur.next.next=cur;
            cur.next=null;
            //节点后移
            cur=cur.next;
        }
        
        //返回最后的那个节点做头节点
        return rev;
    }
原文地址:https://www.cnblogs.com/jiyongjia/p/13296043.html