【算法设计与分析】链表翻转(时间复杂度O(n),空间复杂度O(1)的做法)

匿名 (未验证) 提交于 2019-12-02 23:34:01

问题:


如何在O(n)的时间复杂度,O(1)的空间复杂度内实现这个链表的翻转?



方法:

链表翻转的general做法是,借助一个假链表头(用dummy表示),使用三个指针来完成。以翻转1-->2-->3-->4-->5-->null这个链表为例,链表翻转的过程中,各个链表节点和指针的移动顺序为:
第一步:

       p1  p2  p3                dummy-->1-->2-->3-->4-->5-->null 

第二步:

           p1  p2  p3 dummy-->2-->1-->3-->4-->5-->null 

第三步:

               p1  p2  p3 dummy-->3-->2-->1-->4-->5-->null 

第四步:

                    p1  p2  p3 dummy-->4-->3-->2-->1-->5-->null 

第五步:

                        p1  p2 dummy-->5-->4-->3-->2-->1-->null 
首先看一下各个指针表示的含义:

p1:指针p1指向原链表的头节点,p1在整个链表翻转的过程都只指向原链表的头结点即节点1(节点1也是翻转后链表的尾节点)

p2:指针p2指向翻转过程中,即将变成临时头结点的节点
比如第二步中,p2指向节点3,第三步时节点3就是新的头结点,但是节点3作为头结点是临时的,因为我们会一直翻转,直到整个链表都翻转完,节点5才是最终的头结点。所以节点3只是临时的头结点
(这里只将dummy认做一个辅助节点,而不认做是头结点)

p3:指针p3指向p2的下一个节点

然后看一下翻转的过程:

首先p1 p2 p3分别指向链表的前三个节点:

       p1  p2  p3                dummy-->1-->2-->3-->4-->5-->null 

经过下面的操作可以将链表状态和指针的指向改变为第二步的样子:

p2.next=dummy.next; p1.next=p3; dummy.next=p2;  p2=p3; p3=p2.next; 

(第二步)

           p1  p2  p3 dummy-->2-->1-->3-->4-->5-->null 

重复一遍同样的操作可以将链表状态和指针的指向更新到第三步的状态:

p2.next=dummy.next; p1.next=p3; dummy.next=p2;  p2=p3; p3=p2.next; 

(第三步)

               p1  p2  p3 dummy-->3-->2-->1-->4-->5-->null 

一直进行同样的操作,直到p2指向空节点null,最后的状态为:

                        p1  p2 dummy-->5-->4-->3-->2-->1-->null 

最后返回dummy.next就可以得到翻转后的链表了!!


JAVA实现

当链表中只有1个或者2个节点时,可以直接翻转,不用上面的三个指针的方法
当链表中的节点大于等于三个,就可以使用上面的方法。

public ListNode reverseList(ListNode head) {     // 先检查一下链表的长度,如果链表只有两个节点就直接翻转,不用借助三个指针     int len=0;     ListNode p=head;     while(p!=null) {     	len++;     	p=p.next;     }     if(len==1)	return head;     if(len==2) {     	ListNode newHead=head.next;     	newHead.next=head;     	head.next=null;     	return newHead;      }     		     // 链表长度超过3个节点时,需要借助辅助头节点dummy和三个指针     // dummy的值随便取一个就可以了      ListNode dummy=new ListNode(-1);     dummy.next=head;          ListNode p1=head,p2=p1.next,p3=p2.next;     while(p2!=null) {     	p2.next=dummy.next;     	p1.next=p3;     	dummy.next=p2;     	     	p2=p3;     	if(p2!=null) p3=p2.next;     }     return dummy.next; } 

其中我们的节点结构(ListNode)为:

public class ListNode { 	int val; 	ListNode next;     ListNode(int x) { val = x; } } 
文章来源: https://blog.csdn.net/AXIMI/article/details/90301183
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!