2022-09-10 17:52:27 +03:00
|
|
|
/**
|
2022-09-11 14:15:35 +03:00
|
|
|
* @file
|
2022-09-15 20:34:03 +03:00
|
|
|
* @brief Given a linked list L[0,....,n] of n numbers, find the middle node.
|
2022-09-23 16:24:14 +03:00
|
|
|
*
|
|
|
|
* @details The technique utilized in this implementation is the ["Floyd's
|
|
|
|
* tortoise and
|
|
|
|
* hare"](https://en.wikipedia.org/wiki/Cycle_detection#Floyd's_tortoise_and_hare)
|
|
|
|
* approach. This technique uses two pointers that iterate through the list at
|
|
|
|
* different 'speeds' in order to solve problems. In this implementation, for
|
|
|
|
* every iteration the slow pointer advances one node while the fast pointer
|
|
|
|
* advances two nodes. The result of this is that since the fast pointer moves
|
|
|
|
* twice as fast as the slow pointer, when the fast pointer reaches the end of
|
|
|
|
* the list the slow pointer will be pointing to the middle node of the list.
|
2022-09-10 17:52:27 +03:00
|
|
|
*
|
|
|
|
* Here are some example lists you can use to see how the algorithm works
|
|
|
|
* A = [1,2,3,4,5]
|
|
|
|
* B = [1,2,3,4,5,6]
|
|
|
|
* print median(A) #should be 39
|
|
|
|
* print median(B) #should be 4
|
|
|
|
*
|
|
|
|
* @author [Benjamin Weiss](https://github.com/weiss-ben)
|
2022-09-23 19:14:25 +03:00
|
|
|
* @see median_search.cpp
|
2022-09-10 17:52:27 +03:00
|
|
|
*/
|
|
|
|
|
2022-09-23 16:24:14 +03:00
|
|
|
#include <cassert> /// for assert
|
|
|
|
#include <iostream> /// for IO operations
|
2022-09-17 03:40:03 +03:00
|
|
|
|
2022-09-10 17:52:27 +03:00
|
|
|
/**
|
|
|
|
* Definition for singly-linked list.
|
|
|
|
*/
|
|
|
|
struct ListNode {
|
2022-09-23 13:28:49 +00:00
|
|
|
int val{0}; ///< the value stored in the node
|
|
|
|
ListNode* next{nullptr}; ///< pointer to the next node
|
2022-09-23 16:15:20 +00:00
|
|
|
ListNode() = default; ///< default constructor
|
2022-09-23 13:28:49 +00:00
|
|
|
explicit ListNode(int x)
|
2022-09-23 16:15:20 +00:00
|
|
|
: val(x) {} ///< constructor with value for node->val provided
|
2022-09-23 16:24:14 +03:00
|
|
|
ListNode(int x, ListNode* next)
|
|
|
|
: val(x),
|
|
|
|
next(next) {
|
|
|
|
} ///< constructor with values provided for node->val and node->next
|
|
|
|
};
|
2022-09-10 17:52:27 +03:00
|
|
|
|
|
|
|
/**
|
|
|
|
* @namespace search
|
|
|
|
* @brief Search algorithms
|
|
|
|
*/
|
|
|
|
namespace search {
|
|
|
|
/**
|
|
|
|
* @namespace median_search
|
2022-09-23 16:24:14 +03:00
|
|
|
* @brief Functions for the Median Search algorithm implementation. Wkipedia
|
|
|
|
* link to algorithm: https://en.wikipedia.org/wiki/Median_search
|
2022-09-10 17:52:27 +03:00
|
|
|
*/
|
|
|
|
namespace median_search2 {
|
|
|
|
/**
|
2022-09-23 16:24:14 +03:00
|
|
|
* This function searches for the median of a linked list.
|
|
|
|
* @param head The head of the linked list.
|
|
|
|
* @returns Median node of the linked list.
|
|
|
|
*/
|
2022-09-10 17:52:27 +03:00
|
|
|
ListNode* middleNode(ListNode* head) {
|
2022-09-23 13:28:49 +00:00
|
|
|
if (!head) {
|
2022-09-10 17:52:27 +03:00
|
|
|
return nullptr;
|
2022-09-23 13:28:49 +00:00
|
|
|
}
|
2022-09-23 16:24:14 +03:00
|
|
|
|
|
|
|
// Fast and slow pointers
|
2022-09-23 13:28:49 +00:00
|
|
|
ListNode* fastptr = nullptr;
|
2022-09-10 17:52:27 +03:00
|
|
|
ListNode* slowptr = fastptr = head;
|
2022-09-23 16:24:14 +03:00
|
|
|
|
|
|
|
// fast jumps 2 while slow jumps 1
|
|
|
|
while (fastptr->next && fastptr->next->next) {
|
2022-09-10 17:52:27 +03:00
|
|
|
slowptr = slowptr->next;
|
|
|
|
fastptr = fastptr->next->next;
|
|
|
|
}
|
2022-09-24 01:03:33 +03:00
|
|
|
|
2022-09-10 17:52:27 +03:00
|
|
|
return (fastptr->next) ? slowptr->next : slowptr;
|
|
|
|
}
|
|
|
|
} // namespace median_search2
|
|
|
|
} // namespace search
|
|
|
|
|
|
|
|
/**
|
2022-09-12 14:11:15 +03:00
|
|
|
* @brief Self-test implementations
|
|
|
|
* @returns void
|
2022-09-10 17:52:27 +03:00
|
|
|
*/
|
2022-09-12 14:11:15 +03:00
|
|
|
static void test() {
|
2022-09-24 01:03:33 +03:00
|
|
|
auto* head1 = new ListNode;
|
|
|
|
head1->val = 1;
|
2022-09-23 16:24:14 +03:00
|
|
|
|
2022-09-24 01:03:33 +03:00
|
|
|
ListNode* temp = head1;
|
2022-09-23 16:24:14 +03:00
|
|
|
for (int i = 1; i < 6; ++i) {
|
2022-09-24 01:03:33 +03:00
|
|
|
auto* temp1 = new ListNode;
|
|
|
|
temp1->val = i;
|
2022-09-23 16:24:14 +03:00
|
|
|
|
2022-09-24 01:03:33 +03:00
|
|
|
temp->next = temp1;
|
|
|
|
temp = temp1;
|
2022-09-23 16:24:14 +03:00
|
|
|
}
|
|
|
|
|
2022-09-24 01:03:33 +03:00
|
|
|
ListNode* median = search::median_search2::middleNode(head1);
|
2022-09-23 16:24:14 +03:00
|
|
|
assert(3 == median->val); // 3 is the value of the median node.
|
|
|
|
std::cout << "test case:1 passed\n";
|
2022-09-24 01:03:33 +03:00
|
|
|
|
2022-09-23 16:24:14 +03:00
|
|
|
// Clean up
|
2022-09-24 01:03:33 +03:00
|
|
|
while (head1) {
|
|
|
|
ListNode* t = head1;
|
|
|
|
head1 = head1->next;
|
2022-09-23 16:28:04 +03:00
|
|
|
delete t;
|
2022-09-23 16:24:14 +03:00
|
|
|
}
|
2022-09-24 01:03:33 +03:00
|
|
|
delete head1;
|
|
|
|
delete temp;
|
|
|
|
|
|
|
|
// Test case # 2
|
|
|
|
auto* head2 = new ListNode;
|
|
|
|
head2->val = 1;
|
|
|
|
|
|
|
|
ListNode* temp2 = head2;
|
2022-09-23 16:24:14 +03:00
|
|
|
for (int i = 1; i < 7; ++i) {
|
2022-09-24 01:03:33 +03:00
|
|
|
auto temp3 = new ListNode;
|
|
|
|
temp3->val = i;
|
2022-09-23 16:24:14 +03:00
|
|
|
|
2022-09-24 01:03:33 +03:00
|
|
|
temp2->next = temp3;
|
|
|
|
temp2 = temp3;
|
2022-09-23 16:24:14 +03:00
|
|
|
}
|
|
|
|
|
2022-09-24 01:03:33 +03:00
|
|
|
median = search::median_search2::middleNode(head2);
|
|
|
|
assert(4 == median->val); // 4 is the value of the median node.
|
2022-09-23 16:24:14 +03:00
|
|
|
std::cout << "test case:1 passed\n";
|
|
|
|
|
|
|
|
// Clean up
|
2022-09-24 01:03:33 +03:00
|
|
|
while (head2) {
|
|
|
|
ListNode* t = head2;
|
|
|
|
head2 = head2->next;
|
2022-09-23 16:24:14 +03:00
|
|
|
delete t;
|
|
|
|
}
|
2022-09-24 01:03:33 +03:00
|
|
|
delete head2;
|
|
|
|
delete temp2;
|
|
|
|
|
2022-09-23 16:24:14 +03:00
|
|
|
std::cout << "test case:2 passed\n";
|
|
|
|
std::cout << "--All tests passed--\n";
|
2022-09-10 17:52:27 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2022-09-12 14:11:27 +03:00
|
|
|
* @brief Main function
|
|
|
|
* @returns 0 on exit
|
2022-09-10 17:52:27 +03:00
|
|
|
*/
|
2022-09-23 16:24:14 +03:00
|
|
|
int main() {
|
|
|
|
test(); // run self-test implementations
|
|
|
|
return 0;
|
2022-09-10 17:52:27 +03:00
|
|
|
}
|