LeetCode(92)ReverseLinkedList2
来源:互联网 发布:我的世界服务器linux 编辑:程序博客网 时间:2024/04/28 20:45
题目如下:
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.
分析如下:
把下标范围为[m,n]的节点进行反转,从题例可以看出来,下标从1开始计数。假设,待反转的[m,n]段节点叫做第二段,待反转的[m,n]段节点的左边的节点叫做第一段,待反转的[m,n]段节点的右边的节点叫做第三段。那么,本题最麻烦的地方时,第一段和第三段可能是空的。当m取值为1,n=取值为链表长度length时,这样的情况就会发生。
对于这样的case,我分了情况进行讨论,一共四种情况。这样的代码写出来很长,很容易有bug,基本无法做到20钟之内bugfree。然后网上看了看,有几种解法。
第一种,也是我认为最推荐的,是这里的解法,聪明地简化了代码,只需要讨论第一段是否为空这两种情况,代码很简洁。
第二种,是官网的做法,在head节点之前增加了节点(称作dummy),完全避免了四种情况讨论,这是常见的扬长避短的做法。
第三种,是比较投机取巧的办法,用两个下标,分别指向[m,n]的头m和尾n,先交换节点的值,再向中间靠拢,直到二者相遇为止。这个其实并没有修改节点的链接关系,只是修改了节点的val取值,使得检测的时候呈现的效果和前两种呈现的效果一样。如果题目明确要求不能依靠修改值的方式完成reverse,那么这个方法就挂了。
最好代码:
//我认为最好最简洁的代码,直接偷来了/** * 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) { // Start typing your C/C++ solution below // DO NOT write int main() function if (head == NULL) return NULL; ListNode *q = NULL; ListNode *p = head; for(int i = 0; i < m - 1; i++) { q = p; p = p->next; } ListNode *end = p; ListNode *pPre = p; p = p->next; for(int i = m + 1; i <= n; i++) { ListNode *pNext = p->next; p->next = pPre; pPre = p; p = pNext; } end->next = p; if (q) q->next = pPre; else head = pPre; return head; }};
我的第二版代码:
按照大牛的写法,自己写了一个差不多的。
/** * 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) return NULL; ListNode *q = NULL; //q设定为NULL,p设定为head,这样的好处是,接下来可以用(q==NULL)来判断m是否为1,即head节点是否也参与了reverse,即第一段是否为空。 ListNode *p = head; // for(int i = 0; i < m - 1; i++) { q = p; p = p->next; } ListNode* end = p; //第二段反转后的尾节点。 ListNode* pp=p; ListNode* qq=p->next; ListNode* rr=NULL; for(int i=m;i<n;i++){ //[m,n)区间中进行反转,循环结束后,pp指向第二段翻转后的第一个节点。qq和rr都指向pp的下一个节点,也就是第三段的第一个节点(如果第三段存在),或者NULL节点(如果第三段不存在) rr=qq->next; qq->next=pp; pp=qq; qq=rr; } end->next = qq; if (q) //如果第一段非空 q->next = pp; else //如果第一段为空 head = pp; return head; }};
我的第一版代码:
这是第一次写时,分了第一段、第二段、第三段这几种情况进行考虑。写得很繁琐。
/** * 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(m==n) return head; ListNode* left_neighbor=head; ListNode* right_neighbor=head; ListNode* p=head;//3个进行reverse需要的变量 ListNode* q=head;//3个进行reverse需要的变量 ListNode* r=head;//3个进行reverse需要的变量 ListNode* mn_new_tail=head; //找到左邻居,即第一段的最后一个节点 int count=0; if(m==1){ left_neighbor=NULL; }else{ while(count<m-2){ left_neighbor=left_neighbor->next; count++; } } //找到右邻居,即第三段的第一个节点 if(left_neighbor!=NULL){ right_neighbor=left_neighbor; count=0; while(count<n-m+2){ right_neighbor=right_neighbor->next; count++; } }else{ right_neighbor=head; count=0; while(count<n){ right_neighbor=right_neighbor->next; count++; } } //开始进行翻转,即翻转第二段,[m,n]这段 if(left_neighbor!=NULL){ p=left_neighbor->next; mn_new_tail=p; }else{ p=head; mn_new_tail=p; } if(p!=NULL) q=p->next; if(q!=NULL); r=q->next; while(q!=right_neighbor){ r=q->next; q->next=p; p=q; q=r; } if(left_neighbor!=NULL){ left_neighbor->next=p; mn_new_tail->next=right_neighbor; return head; }else{ mn_new_tail->next=right_neighbor; return p; } }};
update: 2014-12-23
//8ms使用dummy head方式来写,简化代码/** * 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 || m == n) return head; ListNode* dummy_head = new ListNode(-1); dummy_head->next = head; m++; n++; int count = n - m; ListNode* p_m = dummy_head; ListNode* p_m_previous = dummy_head; while (m > 1) { p_m_previous = p_m; p_m = p_m->next; m--; } ListNode* p = p_m; ListNode* q = p_m->next; ListNode* r = q->next; // 因为 1<=m<=n<=length,所以q必然不为NULL,所以不用判断if(p != NULL)后再 r = q->next; //eg: 1 ->2 ->3 -> 4-> 5-> NULL // p q r while (count > 0 ) { q->next = p; p = q; q = r; if (r != NULL) r = r->next; count--; } p_m_previous->next = p; p_m->next = q; head = dummy_head->next; return head; }};
参考资料:
(1) http://www.cnblogs.com/remlostime/archive/2012/11/18/2776273.html
(2) http://discuss.leetcode.com/questions/267/reverse-linked-list-ii#
- LeetCode(92)ReverseLinkedList2
- Leetcode 92
- leetcode 92: Triangle
- LeetCode 92 Rotate List
- LeetCode 92 Decode Ways
- leetcode #92 in cpp
- leetCode练习(92)
- [Leetcode] 2, 92, 86
- leetcode
- [leetcode]
- LeetCode
- leetcode
- leetcode
- leetcode:
- leetcode:
- LeetCode
- leetcode
- LEETCODE
- UVa 644 立即可解码性
- C++编译器与链接器工作原理
- regular~ number~
- hdu 2212
- 如何做不规则的Frame
- LeetCode(92)ReverseLinkedList2
- 2.9 python中的while循环语句 [python入门教程]
- Sicily 1007 To and Fro
- Single Number II
- 优先队列(堆)优先级设置笔记
- ANDROID 在eclipse中没有出现AVD的解决方法
- [PostgreSQL] pg源码src/backend/目录下的结构
- Linux简单总结之命名规则
- sqlserver子查询报错