From 0182e31f7446afe6afb0f1bdd0a88cef731c8f77 Mon Sep 17 00:00:00 2001 From: josuke00 Date: Sat, 24 Jul 2021 22:48:18 +0800 Subject: [PATCH] Added TernarySearch Function --- Search/TernarySearch.js | 104 ++++++++++++++++++++++++++++++ Search/test/TernarySearch.test.js | 36 +++++++++++ 2 files changed, 140 insertions(+) create mode 100644 Search/TernarySearch.js create mode 100644 Search/test/TernarySearch.test.js diff --git a/Search/TernarySearch.js b/Search/TernarySearch.js new file mode 100644 index 000000000..df68cddbf --- /dev/null +++ b/Search/TernarySearch.js @@ -0,0 +1,104 @@ +/* Ternary search is similar to binary search but it divide the sorted array + * into three parts and determine which part the key lies in. The array will + * be divided into three intervals by using two middle points, mid1 and mid2. + * The value of the key will first compared with the two mid points, the value + * will be returned if there is a match. Then, if the value of the key is less + * than mid1, narrow the interval to the first part. Else, if the value of the + * key is greater than mid2, narrow the interval to the third part. Otherwise, + * narrow the interval to the middle part. Repeat the steps until the value is + * found or the interval is empty(value not found after checking all elements). + * + * Reference: https://www.geeksforgeeks.org/ternary-search/ + */ + +/* +* Doctests +* +* > ternarySearchRecursive([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3) +* 2 +* > ternarySearchIterative([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 8) +* 7 +* > ternarySearchRecursive([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 0) +* -1 +* > ternarySearchIterative([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 12) +* -1 +* > ternarySearchRecursive(["Ali", "Cathrynli", "Josuke", "Thomas"], "Cathrynli") +* 1 +* > ternarySearchRecursive(["Ali", "Cathrynli", "Josuke", "Thomas"], "Josuke") +* 2 +* > ternarySearchRecursive(["Ali", "Cathrynli", "Josuke", "Thomas"], "Angela") +* -1 +*/ + +function ternarySearchRecursive (arr, key, low = 0, high = arr.length - 1) { + if (high >= low) { + // find the mid1 and mid2 + const mid1 = Math.floor(low + (high - low) / 3) + const mid2 = Math.floor(high - (high - low) / 3) + + // check if key is found at any mid + if (arr[mid1] === key) { + // return index of key if found + return mid1 + } + if (arr[mid2] === key) { + // return index of key if found + return mid2 + } + + // since the key is not found at mid, + // check in which region it is present + // and repeat the Search operation + // in that region + if (key < arr[mid1]) { + // the key lies in between low and mid1 + return ternarySearchRecursive(arr, key, low, mid1 - 1) + } else if (key > arr[mid2]) { + // the key lies in between mid2 and high + return ternarySearchRecursive(arr, key, mid2 + 1, high) + } else { + // the key lies in between mid1 and mid2 + return ternarySearchRecursive(arr, key, mid1 + 1, mid2 - 1) + } + } else { + // if low > high => we have searched the whole array without finding the item + return -1 + } +} +function ternarySearchIterative (arr, key, low = 0, high = arr.length - 1) { + while (high >= low) { + // find the mid1 and mid2 + const mid1 = Math.floor(low + (high - low) / 3) + const mid2 = Math.floor(high - (high - low) / 3) + + // check if key is found at any mid + if (arr[mid1] === key) { + // return index of key if found + return mid1 + } + if (arr[mid2] === key) { + // return index of key if found + return mid2 + } + + // since the key is not found at mid, + // check in which region it is present + // and repeat the Search operation + // in that region + if (key < arr[mid1]) { + // the key lies in between low and mid1 + high = mid1 - 1 + } else if (key > arr[mid2]) { + // the key lies in between mid2 and high + low = mid2 + 1 + } else { + // the key lies in between mid1 and mid2 + low = mid1 + 1 + high = mid2 - 1 + } + } + // the key was not found + return -1 +} + +export { ternarySearchRecursive, ternarySearchIterative } diff --git a/Search/test/TernarySearch.test.js b/Search/test/TernarySearch.test.js new file mode 100644 index 000000000..5ce269fae --- /dev/null +++ b/Search/test/TernarySearch.test.js @@ -0,0 +1,36 @@ +import { ternarySearchRecursive, ternarySearchIterative } from '../TernarySearch' + +test('should return the index of a number in an array of numbers:', () => { + const indexNumber = ternarySearchRecursive([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 3) + expect(indexNumber).toBe(2) +}) + +test('should return the index of a number in an array of numbers:', () => { + const indexNumber = ternarySearchIterative([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 8) + expect(indexNumber).toBe(7) +}) + +test('should return the index of a number in an array of numbers:', () => { + const indexNumber = ternarySearchRecursive([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 0) + expect(indexNumber).toBe(-1) +}) + +test('should return the index of a number in an array of numbers:', () => { + const indexNumber = ternarySearchIterative([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 12) + expect(indexNumber).toBe(-1) +}) + +test('should return the index of a string in an array of strings:', () => { + const indexNumber = ternarySearchRecursive(['Ali', 'Cathrynli', 'Josuke', 'Thomas'], 'Cathrynli') + expect(indexNumber).toBe(1) +}) + +test('should return the index of a string in an array of strings:', () => { + const indexNumber = ternarySearchRecursive(['Ali', 'Cathrynli', 'Josuke', 'Thomas'], 'Josuke') + expect(indexNumber).toBe(2) +}) + +test('should return the index of a string in an array of strings:', () => { + const indexNumber = ternarySearchRecursive(['Ali', 'Cathrynli', 'Josuke', 'Thomas'], 'Angela') + expect(indexNumber).toBe(-1) +})