-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbinary-search.js
139 lines (121 loc) · 3.52 KB
/
binary-search.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/**
* BinarySearch
* @classdesc Finds the index of a number in an array.
* @see p. 25, p. 47
* @see {@link https://algs4.cs.princeton.edu/code/edu/princeton/cs/algs4/BinarySearch.java.html}
*/
class BinarySearch {
/**
* Iterative implementation of BinarySearch
* @param {[]} a The sorted Array.
* @param {number} key The target key.
* @returns {number} The index of the number in the array or `-1` if not found.
*/
static _iterativeIndexOf (a, key) {
let lo = 0
let hi = a.length - 1
let mid
while (lo <= hi) {
mid = Math.floor(lo + (hi - lo) / 2)
if (key < a[mid]) {
hi = mid - 1
} else if (key > a[mid]) {
lo = mid + 1
} else {
return mid
}
}
return -1
}
/**
* Recursive implementation of BinarySearch
* @param {[]} a The sorted Array.
* @param {number} key The target key.
* @param {number} lo The lower index bound.
* @param {number} hi The higher index bound.
* @returns {number} The index of the number in the array or `-1` if not found.
*/
static _recursiveIndexOf (a, key, lo, hi) {
if (lo > hi) {
return -1
}
const mid = Math.floor(lo + (hi - lo) / 2)
if (key < a[mid]) {
return BinarySearch._recursiveIndexOf(a, key, lo, mid - 1)
} else if (key > a[mid]) {
return BinarySearch._recursiveIndexOf(a, key, mid + 1, hi)
} else {
return mid
}
}
/**
* Returns the index of a number `key` found in an array `a`,
* if `key` is not found, returns `-1`.
* @param {[]} a The sorted Array to search into.
* @param {number} key The target key to search for.
* @returns {number} The index of `key` in the array `a` or `-1` if not found.
*/
static indexOf (a, key) {
return BinarySearch._iterativeIndexOf(a, key)
}
/**
* Returns the index of a number `key` found in an array `a`,
* if `key` is not found, returns `-1`.
* @param {[]} a The sorted Array to search into.
* @param {number} key The target key to search for.
* @returns {number} The index of `key` in the array `a` or `-1` if not found.
*/
static recursiveIndexOf (a, key) {
return BinarySearch._recursiveIndexOf(a, key, 0, a.length - 1)
}
/**
* Returns the count of the items
* in the sorted array that are less
* than the value of the `key`.
* @param {[]} a The sorted array with duplicated keys.
* @param {number} key The value to get the rank.
*/
static rank (a, key) {
const index = this.recursiveIndexOf(a, key)
if (index >= 0) {
let i = index
// loop to the left to find
// the first match with a key
// that is less than `k`
for (; i >= 0; i--) {
if (a[i] !== key) break
}
return i + 1
} else {
// loop to the right
// until find the first match
// with a key greater than `k`
for (let i = 0; i < a.length; i++) {
if (a[i] > key) return i
}
}
}
/**
* Returns the number of values
* that are equal to `key`.
* @param {[]} a The sorted array with duplicated keys.
* @param {number} key The value to count.
*/
static count (a, key) {
const index = this.recursiveIndexOf(a, key)
let _count = 0
if (index === -1) return _count
// count to the left
let left = index - 1
while (left >= 0 && a[left--] === key) {
_count++
}
// count to the right
let right = index + 1
while (right < a.length && a[right++] === key) {
_count++
}
return _count + 1
}
}
module.exports = BinarySearch