版权声明:此文章为许诗宇所写,如需转载,请写下转载文章的地址 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;
}