迭代方法
1. 第m个节点的前一个节点pre和第n个节点;
2. 将第m个节点到第n个节点的链表部分反转;
3. 将pre节点的next指向反转后链表的头节点,将反转后链表的尾节点的next指向n+1节点。
/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
#include <bits/types/struct_tm.h>
#include <cstddef>
class Solution {
public:
/**
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
ListNode* reverseBetween(ListNode* head, int m, int n) {
// write code here
ListNode *new_head=new ListNode(-1);//设置虚拟头节点
ListNode *start, *tmp, *phead;
new_head->next=head;
//找到区间左端点
phead=new_head;
start=head;//start从第一个元素开始
for(int i=1; i<m; i++){
phead=start;
start=start->next;
}
for(int j=1; j<=n-m; j++){
tmp=start->next;
start->next=tmp->next;
tmp->next=phead->next;
phead->next=tmp;
}
return new_head->next;
}
};
设置虚拟头结点的作用
1. 简化链表操作
在链表操作中,如果不使用虚拟头结点,我们需要针对头节点和其他节点分别进行操作,这会导致代码的重复和冗余。而设置虚拟头结点后,我们可以将头节点和其他节点一视同仁,从而简化链表操作的实现。
2. 处理边界情况
当链表为空时,我们需要特殊处理头节点。如果使用虚拟头结点,我们可以省去这个特判,因为虚拟头结点始终存在。
3. 方便删除操作
在链表中,删除头节点时需要特殊处理。如果使用虚拟头结点,我们可以将虚拟头结点作为头节点的前一个节点,从而将删除头节点的操作转化为删除第二个节点的操作,避免了特判。
4. 方便插入操作
在链表中,插入头节点时需要特殊处理。如果使用虚拟头结点,我们可以将虚拟头结点作为头节点的前一个节点,从而将插入头节点的操作转化为插入第二个节点的操作,避免了特判。
综上所述,设置虚拟头结点可以简化链表操作的实现,同时可以避免特判和处理边界情况的麻烦。因此,在链表操作中,设置虚拟头结点是一个常见的技巧。