写博客有一段时间了,刚开始写的时候感觉收获挺多的,每次写完感觉印象挺深刻····过了一段时间,感觉写的也都忘了个差不多了····
再接再厉吧!
链表结构体:
struct node
{
int val;
node* next;
node(int val):val(val),next(NULL){};
};
单链表的反转一个比较好的思路,用三个指针(分别指向三个连续的节点)进行轮转,在循环中,每一次循环转置前两个节点的前后关系,然后将三个指针分别后移,直至循环结束。
原始链表: 1-->2-->3-->4-->NULL
p q r (布置好指针)
1<--2 3-->4-->NULL (反转前两个节点的前后关系)
p q r (指针位置依次后移)
1<--2<--3 4-->NULL (步骤同上)
p q r
1<--2<--3<--4 NULL
p q (r)
可以看出q==NULL是循环结束的条件,而此时r已经不能继续后移了,需要给定一个后移条件,核心语句如下:
q->next=p;
p=q;
q=r;
if(r!=NULL) r=r->next;
LeetCode中的ReverseLinkedList II,要求反转单列表中给定位置(给定初始和结束位置)的部分。思路大同小异,先循环至初始位置(需要记录下初始位置的前一个节点),再进行我们上面的反转过程,最后把反转后的部分嵌入到剩下的链表中即可。唯一需要注意的是初始位置为1的情况,这种情况下头节点是变化的。
代码如下:
class Solution {
public:
ListNode *reverseBetween(ListNode *head, int m, int n) {
if(head==NULL|| head->next==NULL || m==n) return head;
m--;n--;
ListNode* result=head; //最终的头节点
ListNode*tmp_head=head; //初始节点的前一个节点
//找到初始节点
for(int i=0;i<m;++i)
{
tmp_head=head;
head=head->next;
}
ListNode* p=head;
ListNode* q=head->next;
ListNode* r=q->next;
//进行反转
for(int i=m;i<n;++i)
{
q->next=p;
p=q;
q=r;
if(r!=NULL) r=r->next;
}
//将反转后的部分嵌入链表
if(head==tmp_head) result=p; //m=1的情况
else tmp_head->next=p;
head->next=q;
return result;
}
};