您的位置:首页 > 其它

leetcode206/92---Reverse Linked List I/II(反转链表)

2016-01-13 15:09 696 查看

leetcode206-Reverse Linked List

问题描述:

Reverse a singly linked list.

A linked list can be reversed either iteratively or recursively. Could you implement both?

对一个单链表实现反转。

问题求解:

方法一:迭代版本



如图,假设我们调整到节点i处,如果节点i的next直接指向它的前一节点h,将会发生节点断裂,使得我们无法找到节点j,因此为避免断裂,我们应在调整i的next之前把节点j保存下来。再一个要注意的点,调整i的next指针时,除了需要知道节点i本身,还要知道i的前一节点h,因为我们需要把i的next指向h.

因此需要定义3个指针:分别指向当前遍历到的节点cur,它的前一结点pre,以及后一节点next。

最后要注意的点:如何找到翻转后链表的头结点?翻转后链表的头结点是原始链表的尾节点。什么节点是尾节点?自然是next为null的节点!!!!我们用一个指针reverseHead来保存。

/**
* Definition for singly-linked list.
* struct ListNode {
*     int val;
*     ListNode *next;
*     ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public://Iterative版本
ListNode* reverseList(ListNode* head) {
ListNode* reverseHead = NULL;//(1)用来找到反转后链表头结点
ListNode* pre = NULL;//(2)前一结点
ListNode* cur = head;//(3)当前节点
while(cur != NULL)
{
ListNode* next = cur->next;//(4)保存后一节点cur->next
if(next == NULL)
{//找到反转链表的头结点
reverseHead = cur;
}
cur->next = pre;//改变相邻两节点指向
//更新
pre = cur;//将当前节点设置为pre
cur = next;//推进当前节点
}
return reverseHead;
}
};


方法二:递归版本

/**
* Definition for singly-linked list.
* struct ListNode {
*     int val;
*     ListNode *next;
*     ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public://Recursive版本
ListNode* reverseList(ListNode* head) {
return reverse(head, NULL);
}
ListNode* reverse(ListNode* cur, ListNode* pre) {
if(cur == NULL) return pre;
ListNode* next = cur->next;//保存cur->next
cur->next = pre;//改变相邻两节点指向
//更新
return reverse(next, cur);
}
};


leetcode92-Reverse Linked List II

Reverse a linked list from position m to n. Do it in-place and in one-pass.

For example:

Given 1->2->3->4->5->NULL, m = 2 and n = 4,
return 1->4->3->2->5->NULL.


Note:

Given m, n satisfy the following condition:

1 ≤ m ≤ n ≤ length of list.

问题求解:

假设给定
1->2->3->4->5->NULL, m = 2 and n = 4
,我们要对此链表在指定位置处进行反转。

注意的地方:

(1)首先要找到反转的起始节点begin和终止节点end。然后可以利用翻转链表的通用函数进行翻转。

(2)但是别忘了很重要的一点,为了防止在翻转处发生链表断裂,我们在翻转前要找到begin的前一结点和end的后一节点。并在翻转后进行拼接!!!!!

(3)翻转后的部分要特别注意。之前的begin和end的位置已发生对调!!!故end成为了翻转部分的前面节点,begin成为了翻转部分的后面节点。

/**
* Definition for singly-linked list.
* struct ListNode {
*     int val;
*     ListNode *next;
*     ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
if(head==NULL || head->next==NULL || m==n) return head;

ListNode* prehead=new ListNode(0);
prehead->next=head;

ListNode* begin=head;
ListNode* end=head;
ListNode* prebegin=prehead;//1.保存begin的前一结点并初始化
while(--m)
{//2.找到翻转的起始位置以及其前一结点
prebegin = begin;
begin = begin->next;
}
while(--n)
{//3.找到翻转的结束位置
end = end->next;
}
ListNode* nextend=end->next;//4.保存结束位置end的后一结点
reverselist(begin, end);//5.翻转
//6.拼接
prebegin->next = end;//接前面
begin->next = nextend;//接后面
return prehead->next;
}
//翻转链表的通用翻转函数
void reverselist(ListNode* head, ListNode* tail)
{//对给定的链表的一部分(group)进行逆序
ListNode* prehead=new ListNode(0);//(1)首先设置一个前置节点
prehead->next=head;//将前置节点的next设置为头节点
ListNode* curnode=head;//以头节点为当前节点,开始循环
while(prehead != tail)
{
ListNode* tmp=curnode->next;//(2)将当前节点的next赋给一个临时节点
curnode->next=prehead;//然后将当前节点的next指向前置节点
//随后依次位移前置节点指针和当前节点指针1),2)
prehead=curnode;//1)前置节点指针指向当前节点
curnode=tmp;//2)当前节点指针指向临时节点
}
}
};
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode 链表