扯淡
之前听说过google面试反转链表的梗,也尝试着自己实现了一次,算是比较简单的问题。但在纸上手写代码的时候,思维就很乱,可能是隔的时间长忘记了,或者之前就跟本没有理清思路,所以被虐的很惨。
这篇文章的目的就是梳理一下思路,加深印象。如果有更好的算法,留言求虐啊~
描述
这是一个普通的链表,由ABCD4个节点组成,每个节点都包含数据区-data和指向下一个节点的引用-next
反转链表,顾名思义就是将链表每个节点的next引用反过来,如ABCD,变为DCBA。当然,前提是我们只持有头节点的引用,且称为Node a,那么链表反转后的头节点,就是Node d。
分析
要将此链表反转,我们核心的需求是:修改每一个节点的next引用,将next指向前一个节点,将原来的头节点A中的next,指向null。
既然每一个节点都需要操作,那就考虑循环吧,设一个索引(或者称为游标)node(可以利用节点A的引用),从节点A跑到节点D,当它再往后移动指向null时,循环结束。那么循环边界条件则为
while(node != null){
//do something
}
然后我们再看看每个节点做一次反转(即每次循环),都需要做什么事情
在修改当前节点的next引用之前,要先保存其值,为了避免丢失下一个节点(即
Node next
)的引用。进行反转,修改当前节点的next,使之指向上一个节点(即
Node last
)要保存当前节点的引用,为了提供给下一次循环时,对下个节点进行反转
为了保证while循环可以从头节点A遍历到尾节点D,那么游标node在循环体最后要向后移动一个节点,即指向下一个节点。
代码
Node reversalLinkedList(Node node){
Node last = null;
Node next = null;
while(node != null){
next = node.getNext();//1 拿到下个节点的引用,为了提供给第4步使node向链表后方移动
node.setNext(last);//2 将当前节点指向上一个节点
last = node;//3 将last指向当前节点,提供给下次循环的第2步
node = next;//4 将当前节点的引用(即游标)指向下一个节点
}
/*
* 循环完成后,node和next都指向了原节点D的next指向的位置,即null
* 而last指向了上述null前面的位置,即节点D
* 将last返回,则得到链表ABCD反转后链表DCBA的头节点D
*/
return last;
}
逻辑其实很简单,需要注意的就是每次循环时需要暂存的引用 -- next,last
图解
每次循环其实就是修改当前节点next的引用+三个引用(last,node,next)的后移,如下图
第一次循环前
第一次循环的过程
第一次循环结束后
最后全部反转后
总结
保存当前节点,上一个节点,下一个节点的引用
每次循环最后,当前节点向后移动
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。