leetcode-206-反转链表(reverse linked list)-java

版权声明:此文章为许诗宇所写,如需转载,请写下转载文章的地址 https://blog.csdn.net/xushiyu1996818/article/details/82181124

题目及用例

package pid206;
/*反转链表

反转一个单链表。

示例:

输入: 1->2->3->4->5->NULL
输出: 5->4->3->2->1->NULL

进阶:
你可以迭代或递归地反转链表。你能否用两种方法解决这道题?



*/


import pid206.LinkList;
import pid206.LinkList.ListNode;

public class main {


    public static void main(String[] args) {

        LinkList a=new LinkList(1);
        a.addLast(2);
        a.addLast(5);

        LinkList b=new LinkList(-5);
        b.addLast(0);
        b.addLast(500);

        a.printList();
        test(a.first);

        b.printList();
        test(b.first);
    }

    private static void test(ListNode ito) {
        Solution solution = new Solution();
        ListNode rtn;
        long begin = System.currentTimeMillis();
        System.out.println();
        //开始时打印数组

        rtn=solution.reverseList(ito);//执行程序
        long end = System.currentTimeMillis();  

        LinkList a=new LinkList(0);
        a.first=rtn;
        a.printList();

        //System.out.println(":rtn" );
        //System.out.print(rtn);
        System.out.println();
        System.out.println("耗时:" + (end - begin) + "ms");
        System.out.println("-------------------");
    }

}

linklist

package pid206;


public class LinkList {
    public class ListNode {
      public int val;
      public ListNode next;
      ListNode(int x) 
      { val = x; 
        next=null;
      }
      public ListNode() {
          val=0;
          next=null;
      }

      public void printNodeToEnd(){
        ListNode a=this;
        System.out.println("print node to end");
        while(a!=null){//直到最后一个不为空的节点
            System.out.print(a.val+"  ");
            a=a.next;
        }
        System.out.println();
      }
    }

    ListNode first;

    public LinkList(int x){
        first=new ListNode(x);
        first.next=null;
    }
    public LinkList(){
        first=null;
        first.next=null;
    }

    public void addLast(int x){

        if(first==null){
            first=new ListNode(x);
            return;
        }
        ListNode a=first;
        while(a.next!=null){
            a=a.next;
        }
        ListNode b=new ListNode(x);
        a.next=b;
    }

    public void printList(){
        ListNode a=first;
        System.out.println("print listnode");
        while(a!=null){//直到最后一个不为空的节点
            System.out.print(a.val+"  ");
            a=a.next;
        }
        System.out.println();
    }



}

解法1(成功,29ms,超级慢)
速度o(n^2),从头到尾,找到最后一个,将最后一个截断给结果

package pid206;

import pid206.LinkList;
import pid206.LinkList.*;
/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    public ListNode reverseList(ListNode head) {
        if(head==null){
            return null;
        }
        if(head.next==null){
            return head;
        }

        ListNode end=null;//结果的开头
        ListNode endnow=null;//每次结果的最后

        while(true){
            ListNode temp=head;
            if(temp.next==null){//此时为最后一个
                endnow.next=temp;
                endnow=endnow.next;
                endnow.next=null;
                head=null;
                break;
            }

            while(temp.next.next!=null){
                temp=temp.next;

            }//直到temp为head的倒数第二个

            if(end==null){//第一次
                end=temp.next;
                endnow=end;
                temp.next=null;
            }
            else{//中间
                endnow.next=temp.next;
                endnow=endnow.next;
                temp.next=null;
            }

        }


        return end;
    }
}

解法二(别人的,很好,应该速度很快)
迭代的方法,将head从头往后遍历
将每个东西塞到另一个链表的头部
1 2 3 4 5
1 为头
2.next=1
3.next=2
这里写图片描述
边界值判断:
head == null // 空链表,无需反转,返回null 即 head
head.next == null // 只有一个节点的链表,无需反转,返回head
变量注释:
p // ListNode类型,当前节点的前一个节点,即反转链表的头节点,初始值为null
q // ListNode类型,当前节点的下一个节点,初始值为null
解题思路:
从前往后遍历,每次将当前节点 并入 反转的链表,所以循环条件是head != null
重点:将当前节点 并入 反转的链表 // 每次循环执行的操作
(1)每次进行操作前,需要先保存当前节点的下一个节点 q = head.next
(2)将当前节点并入 左边的反转链表 中,即当前节点 指向 前一个节点,head.next = p
(3)维护变量,保存新的p,head。即 p = head; head = q;
循环结束时,head = null 即head在原链表的尾节点之后
p 为 原链表 的尾节点,即反转链表后的 头节点,所以最后返回的是 节点p

public ListNode reverseList(ListNode head) {
    if (head == null || head.next == null)
        return head;
    ListNode p = null;
    ListNode q = null;
    while (head != null) {
        q = head.next;
        head.next = p;
        p = head;
        head = q;
    }
    return p;
}

猜你喜欢

转载自blog.csdn.net/xushiyu1996818/article/details/82181124