声明
该系列文章仅仅展示个人的解题思路和分析过程,并非一定是优质题解,重要的是通过分析和解决问题能让我们逐渐熟练和成长,从新手到大佬离不开一个磨练的过程,加油!
原题链接
算法分析
问题转换:反转链表 <=> 反转节点 <=> 节点前驱和后继的指向交换
问题细化:
(1)变量:需要有一个指针cur指向链表头节点,负责遍历链表;需要有一个临时变量pre用于存储cur所指向节点的前驱节点;需要有一个临时变量temp用于存储cur所指向节点的后继节点。
(2)逻辑主体:
①temp = cur.next;
②cur.next = pre;
③pre = cur;
④cur = temp;
具体的交换过程示例如图1,图2。
代码示例(C#)
public ListNode ReverseList(ListNode head)
{
if(head == null) return null;
ListNode cur, temp, pre;
cur = head;
pre = null;
while(cur != null)
{
temp = cur.next;
cur.next = pre;
pre = cur;
cur = temp;
}
return pre;
}
算法解说
对于这道题,我们希望能够在原链表的基础上直接去实现链表的反转从而减少不必要的内存开销,对于链表的反转实际上就是对链表上的每一个节点进行反转。这里我们针对双向链表和单向链表的节点反转分别进行讲解。
对于双向链表而言节点的反转就是改变前驱和后继指针的指向,让前驱指针指向原本后继指针指向的节点以及让后继指针指向原本前驱指针指向的节点。而对于单向链表而言只存在前驱和后继指针中的一个,但是它的节点反转与双向链表本质上是一样的。
实际上双向链表中单个节点反转的过程与数组中两个不同位置的元素进行交换的过程相似,数组中元素的交换需要临时存储其中一个元素,避免在交换过程中元素被覆盖或丢失,那么对于节点反转也是如此,我们需要临时存储前驱指针指向的节点或者后继指针指向的节点,但是对于单向链表而言二者都需要进行临时存储。
接下来将思路转换为代码需要明确变量和逻辑主体。本题是针对单向链表的反转,所以我们需要三个变量,一个变量用于临时存储前驱指针指向的节点,一个变量用于指向当前节点,还有一个变量用于临时存储后继指针指向的节点。逻辑主体则是从链表头节点开始依次反转当前节点的前驱和后继指向,同时要注意结束条件。