已知链表头节点指针head,将链表从位置m到n逆序。(不申请额外空间)
#include<stdio.h>
struct ListNode
{
int val; //数据域
ListNode* next; //指针域
ListNode(int x): val(x),next(NULL) {} //构造函数
};
class Solution
{
public:
Solution(){}
~Solution(){}
ListNode* reverseBetween(ListNode* head, int m, int n)
{
int change_len = n - m + 1;
ListNode* pre_head = NULL;
ListNode* result = head;
while (head && --m)
//如果为while (head && --m),m先自减再判断,判断时经过自减后是从m-1到1,m本身是从m到2,共m-1次循环
//如果为while (head && m--),m先判断再自减,判断时未自减是从m到1,m本身是从m到1,共m次循环
{
pre_head = head;
head = head->next;
} //循环结束时head到达第m个节点, pre_head到达第m-1个节点
ListNode* modify_list_tail = head; //此时为第m个节点
ListNode* new_head = NULL; //原逆序部分的尾部
while (head && change_len--) //共逆序change_len次
{
//第一个循环开始时head在第m个节点, next在第m+1个节点,结束时head在第m+1个节点。
//第二个开始循环时,head在第m+1个节点,next在第m+2个节点,结束时head在第m+2个节点。
//第change_len个循环开始时,head在第m+change_len-1=m+n-m+1-1=n个节点,结束时head在第n+1个节点。
ListNode* next = head->next; //备份。
head->next = new_head; //将原顺序序列的第一个元素的指针指向新逆序序列
new_head = head; //将新逆序序列的头指向新加的节点
head = next; //将原顺序序列的指针移至后一个节点
//change_len--;
} //循环结束时head到达n+1,new_head到达n,
modify_list_tail->next = head; //将逆序尾链接到n+1
if (pre_head)
{
pre_head->next = new_head; //将n-1个节点中的指针指向第n个节点。
}
else
{
result = new_head;
}
return result;
}
};
int main()
{
ListNode a(1);
ListNode b(2);
ListNode c(3);
ListNode d(4);
ListNode e(5);
ListNode f(6);
ListNode g(7);
ListNode h(8);
a.next = &b;
b.next = &c;
c.next = &d;
d.next = &e;
e.next = &f;
f.next = &g;
g.next = &h;
Solution solve;
ListNode* head = solve.reverseBetween(&a, 4, 7);
while (head)
{
printf("%d\n", head->val);
head = head->next;
}
return 0;
}
运行结果:
1
2
3
7
6
5
4
8