题目描述:
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
示例:
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
输入:head = [5], left = 1, right = 1
输出:[5]
解题思路:
反转链表的一部分,首先需要找到这部分结点,保留左侧结点的前驱节点和右侧结点的后继结点。
然后对中间这部分链表进行反转。
对于链表的反转,有递归和迭代两种常见方法
迭代法
struct ListNode* reverseList(struct ListNode* head){
if(head==NULL || head->next == NULL)
return head;
struct ListNode *left,*right,*temp;
left = NULL;
right = head;
while(right)
{
temp = right->next;
right->next = left;
left = right;
right = temp;
}
return left;
}
递归法
struct ListNode *reverseList(struct ListNode *head)
{
if(head == NULL || head->next == NULL)
return head;
struct ListNode *newHead;
newHead = reverseList(head->next);
head->next->next = head;
head->next = NULL;
return newHead;
}
由于需要保留左侧结点的前驱,当左侧结点刚好时头结点的时候需要分类讨论,比较麻烦,所以创建一个新的头结点,这样就避免了分类讨论。
struct ListNode* reverseBetween(struct ListNode* head, int left, int right){
//先对特殊情况讨论,其中left == right时相等于没有反转,直接返回即可
if(head == NULL || head->next == NULL || left == right)
return head;
struct ListNode *leftNode,*rightNode,*p;
struct ListNode newHead;
newHead.next = head; //使用新的头结点
int n=0;//n用于计数
p=&newHead;
//遍历链表 寻找left的前驱leftNode 和 right的后继rightNode
while(p)
{
if( n+1 == left)
leftNode = p;
if(n == right)
{
rightNode = p->next;
p->next = NULL;
break;
}
n++;
p=p->next;
}
//结束循环 leftNode 为left的前一个结点 rightNode 为 rigth 的后一个结点
leftNode->next = reverseList(leftNode->next);//反转链表 重新连接链表
p=leftNode->next;
while(p->next)
{
p=p->next;
}
p->next = rightNode;
return newHead.next;
}