From f6c56f7e8e1e55c72a5158ab90d8a15d439ace26 Mon Sep 17 00:00:00 2001 From: Christopher Friedt Date: Sun, 6 Dec 2020 13:13:51 -0500 Subject: [PATCH 1/2] Implement linked-list-cycle-ii https://leetcode.com/problems/linked-list-cycle-ii time: 16ms time-rank: 21.04% time-complexity: O(N) space: 10MB space-rank: 9.36% space-complexity: O(N) Fixes #228 Signed-off-by: Christopher Friedt --- linked-list-cycle-ii-test.cpp | 64 +++++++++++++++++++++++++++++++++++ linked-list-cycle-ii.cpp | 58 +++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+) create mode 100644 linked-list-cycle-ii-test.cpp create mode 100644 linked-list-cycle-ii.cpp diff --git a/linked-list-cycle-ii-test.cpp b/linked-list-cycle-ii-test.cpp new file mode 100644 index 0000000..e261938 --- /dev/null +++ b/linked-list-cycle-ii-test.cpp @@ -0,0 +1,64 @@ +/* + * MIT License + * + * Copyright (c) 2018 Christopher Friedt + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +#include + +#include "util/ListNode.cpp" + +#include "linked-list-cycle-ii.cpp" + +TEST(LinkedListCycleIi, Test_3_2_0_n4__1) { + vector nodes = { + ListNode(3), + ListNode(2), + ListNode(0), + ListNode(-4), + }; + nodes[0].next = &nodes[1]; + nodes[1].next = &nodes[2]; + nodes[2].next = &nodes[3]; + nodes[3].next = &nodes[1]; + EXPECT_EQ(&nodes[1], Solution().detectCycle(&nodes[0])); +} + +TEST(LinkedListCycleIi, Test_1_2__0) { + vector nodes = { + ListNode(1), + ListNode(2), + }; + nodes[0].next = &nodes[1]; + nodes[1].next = &nodes[0]; + EXPECT_EQ(&nodes[0], Solution().detectCycle(&nodes[0])); +} + +TEST(LinkedListCycleIi, Test_1_n1) { + vector nodes = { + ListNode(1), + }; + nodes[0].val = 1; + nodes[0].next = NULL; + EXPECT_EQ(NULL, Solution().detectCycle(&nodes[0])); +} diff --git a/linked-list-cycle-ii.cpp b/linked-list-cycle-ii.cpp new file mode 100644 index 0000000..6707150 --- /dev/null +++ b/linked-list-cycle-ii.cpp @@ -0,0 +1,58 @@ +/* + * MIT License + * + * Copyright (c) 2018 Christopher Friedt + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include + +using namespace std; + +// https://leetcode.com/problems/linked-list-cycle-ii + +class Solution { +public: + ListNode *detectCycle(ListNode *head) { + unordered_set visited; + ListNode *it; + for (it = head; it != NULL; it = it->next) { + if (visited.end() != visited.find(it)) { + return it; + } + visited.insert(it); + } + return it; + } + + /* + // Recursive solution (obviously better to use iterative) + ListNode *helper(unordered_set &visited, ListNode *n) { + if (NULL == n) { + return NULL; + } + if (visited.end() != visited.find(n)) { + return n; + } + visited.insert(n); + return helper(visited, n->next); + } + */ +}; From 77a8eebd5f18f946b102b778754a79f62d762277 Mon Sep 17 00:00:00 2001 From: Christopher Friedt Date: Sun, 6 Dec 2020 13:42:31 -0500 Subject: [PATCH 2/2] Implement linked-list-cycle-ii https://leetcode.com/problems/linked-list-cycle-ii time: 4ms time-rank: 98.90% time-complexity: O(N) space: 7.8MB space-rank: 89.71% space-complexity: O(1) This solution adds no extra space but destroys the input. While the cost of checking if a node is visited is still O(1), this solution is faster than an unordered_set lookup because no hashing is performed, values are likely still in cache, and it is simply a const comparison. Fixes #228 Signed-off-by: Christopher Friedt --- linked-list-cycle-ii.cpp | 24 +++++------------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/linked-list-cycle-ii.cpp b/linked-list-cycle-ii.cpp index 6707150..7b001ab 100644 --- a/linked-list-cycle-ii.cpp +++ b/linked-list-cycle-ii.cpp @@ -22,37 +22,23 @@ * SOFTWARE. */ -#include - using namespace std; // https://leetcode.com/problems/linked-list-cycle-ii +#define CYCLE 0xc7c1e + class Solution { public: + // this solution is destructive of the input, but it's O(1) space complexity ListNode *detectCycle(ListNode *head) { - unordered_set visited; ListNode *it; for (it = head; it != NULL; it = it->next) { - if (visited.end() != visited.find(it)) { + if (it->val == CYCLE) { return it; } - visited.insert(it); + it->val = CYCLE; } return it; } - - /* - // Recursive solution (obviously better to use iterative) - ListNode *helper(unordered_set &visited, ListNode *n) { - if (NULL == n) { - return NULL; - } - if (visited.end() != visited.find(n)) { - return n; - } - visited.insert(n); - return helper(visited, n->next); - } - */ };