题目
逻辑实现
这里我们采取第二种方式来讲解:
转链表是计算机算法和数据结构中一个常见的题目。链表是一种常见的基础数据结构,它由一系列结点组成,每个结点包含数据域和指向下一个结点的指针。
要反转一个链表,基本的思路是遍历原链表,在遍历过程中改变每个结点的指针方向,使其指向前一个结点,从而得到一个新的链表,其结点的顺序与原链表相反。
下面是反转单向链表的一般步骤:
- 定义三个指针:
pre
(前驱结点)、cur
(当前结点)和next
(下一个结点)。- 将
pre
初始化为NULL
,它将用来跟踪反转后的链表的末尾。- 从链表的头结点开始,将
cur
指向头结点,next
指向cur
的下一个结点。- 在每次迭代中:
- 将
cur
的下一个结点设置为pre
,即改变指针方向。- 将
pre
向前移动一步,即pre
现在指向cur
。- 将
cur
向前移动一步,即cur
现在指向next
。- 如果
cur
不是链表的最后一个结点,则设置next
为cur
的下一个结点。- 当
cur
变为NULL
时,说明已经遍历完整个链表,此时pre
指向的就是新的头结点。单趟实现
循环实现
代码实现
/** * struct ListNode { * int val; * struct ListNode *next; * }; */ /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param head ListNode类 * @return ListNode类 */ //三指针解决 //保存上一个节点,当前节点,下一个节点 struct ListNode* ReverseList(struct ListNode* head ) { if(head==NULL) return NULL; // 这里的前后指针初始的时候需要指向空,因为可能存在几种情况,比如是空,prev是当前节点的上一个节点,本身就是空,所以初始的时候需要指向null struct ListNode* cur=head; struct ListNode* prev=NULL; struct ListNode* next=NULL; //这一步放到这里的关键在于,节点的尾部的下一个节点刚好是null,所以放在这个位置,不然导致死循环 while (cur) { next=cur->next; cur->next=prev; prev=cur; cur=next; } //这里需要知道的是,最后cur和next都会越界,所以我们需要返回的数值是prev return prev; }
解释:
函数定义:
struct ListNode* ReverseList(struct ListNode* head);
这个函数接受一个
ListNode
类型的指针head
,它是链表的头节点。函数返回一个ListNode
类型的指针,即反转后链表的新头节点。空链表检查:
if(head == NULL) return NULL;
如果传入的头节点
head
是NULL
,表示链表为空,直接返回NULL
。初始化指针:
struct ListNode* cur = head; struct ListNode* prev = NULL; struct ListNode* next = NULL;
cur
用于遍历链表,初始化为头节点。prev
指向当前节点的前一个节点,初始化为NULL
。next
用于临时存储当前节点的下一个节点,初始化为NULL
。反转链表:
while (cur) { next = cur->next; cur->next = prev; prev = cur; cur = next; }
这是一个循环,遍历原始链表的所有节点:
- 存储当前节点
cur
的下一个节点到next
。- 将当前节点
cur
的next
指针指向其前一个节点prev
,实现反转。- 将
prev
更新为当前节点cur
。- 将
cur
更新为next
,即移动到下一个节点。返回新头节点:
return prev;
循环结束后,
prev
将指向原始链表的最后一个节点,它成为了反转后链表的新头节点。循环的结束条件: 当
cur
为NULL
时,循环结束。此时,原始链表的尾节点的next
指针已被设置为NULL
,避免了死循环。函数的返回值: 函数返回
prev
,它是反转后链表的新头节点。这个算法的时间复杂度是 O(n),其中 n 是链表的长度,因为我们需要遍历链表中的每个节点一次。空间复杂度是 O(1),因为我们只使用了有限数量的额外指针变量,不依赖于输入链表的大小。
注意事项
1,
// 这里的前后指针初始的时候需要指向空,因为可能存在几种情况,比如是空,prev是当前节点的上一个节点,本身就是空,所以初始的时候需要指向null
2,
这里需要了解的是,这里我们最后的cur和next都会产生越界行为,所以我们最后返回的是prev
3,
这里的cur->next=prev位置不能放到最后,应该放到第二个,因为我们最后指向的空节点
所以,我们应该先指向上个节点