题解 | #链表内指定区间反转#
链表内指定区间反转
http://www.nowcoder.com/practice/b58434e200a648c589ca2063f1faf58c
```/**
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*
* C语言声明定义全局变量请加上static,防止重复定义
*/
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param head ListNode类
* @param m int整型
* @param n int整型
* @return ListNode类
*/
struct ListNode* reverseBetween(struct ListNode* head, int m, int n ) {
// write code here
struct ListNode *The_M_p, *The_Mminus1_p; // 声明两个指针变量;一个是第m-1个结点,一个是m个结点;
The_M_p = head; The_Mminus1_p = head; // 为什么要两个呢?因为改变链表后,结点地址自然也就改变1;
for(int i = 1; i < m-1; i++) { // 而最后要将改变的地址两端重新衔接上;
The_Mminus1_p = The_Mminus1_p->next;
}
if(m != 1) The_M_p = The_Mminus1_p->next; // 这里是若m == 1时的情况,m==1情况特殊;
else The_M_p = head; // 我定义The_M_p 和 The_Mminus1_初始地址相同,均为head;
// 所以m==1时,The_M_p也应该等于head;
struct ListNode *The_N_p, *The_Nadd1_p; // 第n个值同理,只不过,这时是第n个 和 第n+1 个,
The_N_p = head; The_Nadd1_p = head; // 不过我这个程序不用while语句,所以只用第n+1个, 用来衔接;
for(int i = 1; i < n; i++) {
The_N_p = The_N_p->next;
}
// m to n 逆序;用无头结点的头插法即可;
The_Nadd1_p = The_N_p->next;
struct ListNode *q, *p, *record;
record = The_M_p;// 记录第m个结点的地址;地址地址地址,//狭义的理解:结点的地址不会改变;
q = The_M_p;
for(int i = m-1; i < n; i++) { // Notice: 这个是循环(n-m+1)次,因为刚开始是自身交换哦//(
q = The_M_p;
The_M_p = The_M_p->next;
q->next = p;// 头插法 //核心代码
p = q; // 头插法 //核心代码
}
if(m == 1) { // m == 1 是个特殊的情况;
head = p; // 因为m == 1时,The_M_p == The_Mminus1_p == record == 首元结点的地址;
} else {
The_Mminus1_p->next = p;
}
record->next = The_Nadd1_p;
return head;
}
/*
{1,2,3,4,5} 2,4;
1 -> 2 -> 3 -> 4 ->5;
//head.val = 1;
//The_Mminus1_p.val = 1;
//The_Nadd1_p.val = 5;
交换2 -> 3 -> 4; Notice: 1 -> 2 & 4 -> 5哦;
头插法交换完后:|----未知(因为没有给分配,详见line36)
1 4 -> 3 -> 2 5
|-------------|(1 -> 2;
所以这时要把m 和n处衔接上;
就是line45 to line50;
{1,2,3,4,5} 1,3;
这个例子特殊,
因为m == 1;
可以自己推一下试试;
综上所述:我的题解就讲完了,第一次发题解,望见谅;;
*/