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)当前节点指针指向临时节点 } } };
相关文章推荐
- [C/C++]反转链表
- C#实现基于链表的内存记事本实例
- C语言实现带头结点的链表的创建、查找、插入、删除操作
- C++实现简单的学生管理系统
- Linux内核链表实现过程
- C++链表倒序实现方法
- C#通过链表实现队列的方法
- C#实现的简单链表类实例
- 找出链表倒数第n个节点元素的二个方法
- Java数据结构之简单链表的定义与实现方法示例
- C语言单循环链表的表示与实现实例详解
- C++实现的链表类实例
- PHP小教程之实现链表
- C语言双向链表的表示与实现实例详解
- js链表操作(实例讲解)
- C语言实现输出链表中倒数第k个节点
- C++语言实现线性表之链表实例
- STL list链表的用法详细解析
- C语言创建链表错误之通过指针参数申请动态内存实例分析
- php链表用法实例分析