LeetCode-Linked List Cycle II
2015-08-01 15:04
399 查看
题目:LeetCode-Linked List Cycle II
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
Follow up:
Can you solve it without using extra space?
解释:
做了1就忍不住要做2,这道题要求高了一点。要返回开始循环的节点,那么你肯定得找到这个节点。怎么找?循环链表中,有且只有两个节点的指针域是相同的,并且相同的两个指针就是指向循环开始的节点的,所以可以根据这一点来寻找循环链表的开始节点。
要实现这个要求,有一个比较直接的方法,即逐个比较法。就是用两个指针,一个在循环部分不断的循环(指针 fast),一个从链表的头指针开始移动(指针slow),slow每移动一次,fast 移动一圈,依次比较他们是否相同(虽然感觉这样的时间负责度会很大,但这总比不做好吧)。实现代码如下:
运行,程序通过,不过果然,运行时间72Ms,离系统记录的12Ms还差很多,这时就要改进代码了。
再仔细观察一下循环链表的特点,发现在一个循环链表中,快慢指针相遇的点总是固定的某点,如图中的3处,因为快指针一定要比慢指针快了一圈,它们才有可能相遇。再假设它们是完全循环链表,那么它们相遇点肯定是第一个节点,那么非完全循环链表为什么不是相遇在开始的节点处呢?因为它事先跑了一段无关的路了呀(图中的1~2段),也正是因为它们跑了一段路了,所以相当于它们在3处开始移动的,也就是说明了什么?说明1~2段和2~3段的路程是相同的!!所以一个指针从链头开始,一个指针从相遇处开始,同步移动,它们必然会在循环开始处相遇,这样也就找出来题求的节点了。
代码如下:
运行用时12Ms。这是完全自己写的代码,还没看大神们的代码,不知是否相同。虽然思考这道题时用了不少时间,但看到自己的代码被access时,觉得还是值得的。
Given a linked list, return the node where the cycle begins. If there is no cycle, return null.
Follow up:
Can you solve it without using extra space?
解释:
做了1就忍不住要做2,这道题要求高了一点。要返回开始循环的节点,那么你肯定得找到这个节点。怎么找?循环链表中,有且只有两个节点的指针域是相同的,并且相同的两个指针就是指向循环开始的节点的,所以可以根据这一点来寻找循环链表的开始节点。
要实现这个要求,有一个比较直接的方法,即逐个比较法。就是用两个指针,一个在循环部分不断的循环(指针 fast),一个从链表的头指针开始移动(指针slow),slow每移动一次,fast 移动一圈,依次比较他们是否相同(虽然感觉这样的时间负责度会很大,但这总比不做好吧)。实现代码如下:
class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode *slow, *fast; ListNode *p = NULL; slow = fast = head; while(1) { if(fast == NULL || fast->next == NULL ) return NULL; slow = slow->next; fast = fast->next->next; if(slow == fast) { p = slow; //记录当前节点,作是否循环一圈的判断 slow = head; while(1) { if(slow == fast) return slow; fast = fast->next; if(fast == p) { slow = slow->next; //当fast回到P处 //时,即循环完了一圈,此时slow移动一位. } } } } } };
运行,程序通过,不过果然,运行时间72Ms,离系统记录的12Ms还差很多,这时就要改进代码了。
再仔细观察一下循环链表的特点,发现在一个循环链表中,快慢指针相遇的点总是固定的某点,如图中的3处,因为快指针一定要比慢指针快了一圈,它们才有可能相遇。再假设它们是完全循环链表,那么它们相遇点肯定是第一个节点,那么非完全循环链表为什么不是相遇在开始的节点处呢?因为它事先跑了一段无关的路了呀(图中的1~2段),也正是因为它们跑了一段路了,所以相当于它们在3处开始移动的,也就是说明了什么?说明1~2段和2~3段的路程是相同的!!所以一个指针从链头开始,一个指针从相遇处开始,同步移动,它们必然会在循环开始处相遇,这样也就找出来题求的节点了。
代码如下:
class Solution { public: ListNode *detectCycle(ListNode *head) { ListNode *slow, *fast; ListNode *p = NULL; slow = fast = head; while(1) { if(fast == NULL || fast->next == NULL ) return NULL; slow = slow->next; fast = fast->next->next; if(slow == fast) { slow = head; while(1) { if(slow == fast) return slow; slow = slow->next; fast = fast->next; } } } } };
运行用时12Ms。这是完全自己写的代码,还没看大神们的代码,不知是否相同。虽然思考这道题时用了不少时间,但看到自己的代码被access时,觉得还是值得的。
相关文章推荐
- Javascript实现关联数据(Linked Data)查询及注意细节
- leetcode 179 Largest Number
- leetcode 24 Swap Nodes in Pairs
- leetcode 2 Add Two Numbers 方法1
- leetcode 2 Add Two Numbers 方法2
- 底版本编译时找不到高版本框架里的对象。那么就改成弱链接。就能通过编译了
- 如何查看Linux是32位还是64位
- linux查看系统版本(32位/64位)的方法
- ArrayList vs. LinkedList vs. Vector
- [LeetCode]47 Permutations II
- [LeetCode]65 Valid Number
- [LeetCode]123 Best Time to Buy and Sell Stock III
- [LeetCode] String Reorder Distance Apart
- [LeetCode] Sliding Window Maximum
- [LeetCode] Find the k-th Smallest Element in the Union of Two Sorted Arrays
- [LeetCode] Determine If Two Rectangles Overlap
- [LeetCode] A Distance Maximizing Problem
- leetcode_linearList
- leetcode_linearList02
- LeetCode[Day 1] Two Sum 题解