给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
这题写了好多次,老是记不住关键点。
比如输入的是 1,2,3,4,5,6,7,8。
2,6。也就是要反转为1,6,5,4,3,2,1,7,8.
大致思路就是,先找到要移动的第一个节点的前一位(叫它pre吧),然后用一个指针(叫它cur吧)指向第一个要移动的结点开始循环,每次循环都会把cur的下一位移动到pre的下一位,期间cur一直指向一个结点。大致过程是
1 2 3 4 5 6 7 8//cur指向2,cur的下一位是3,把3移动到pre的下一位,也就是1的下一位。
1 3 2 4 5 6 7 8//cur还是指向2,cur的下一位是4,把4移动到pre的下一位
1 4 3 2 5 6 7 8//cur还是指向2,下一位是5......
1 5 4 3 2 6 7 8
1 6 5 4 3 2 7 8
代码如下
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
ListNode *dummy = new ListNode();//很关键,首先方便了以后找left的前一位,而且如果left等于1(也就是从第一个点开始反转,直接return head会少丢掉被反转的元素),最后return dummy->next是不会错的
dummy->next = head;
ListNode *pre = dummy;//pre要指向要反转的元素的前一个元素
int i;
for(i = 0; i < left - 1; i++)//移动pre到left的前一位
{
pre = pre->next;
}
ListNode* cur = pre->next;//cur指向当前需要反转的结点
for(i = left; i < right; i++)
{
ListNode* p = cur->next;//p来保存cur的下一位的地址
cur->next = p->next;//断开cur和p的连接,让cur指向p的下一位
p->next = pre->next;//断开p和下一位的连接,让p指向pre的下一位(千万别写成p->next = cur,cur的位置是一直在变的,而pre->next一直都是那个地方)
pre->next = p;//断开pre和cur的连接,让pre的下一位为p
}
return dummy->next;
}
最关键的就是
p->next = pre->next;
//不要写成 p->next = cur;
还有最后返回的是dummy->next而不是head