-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy path03.searching.js
169 lines (138 loc) · 4.18 KB
/
03.searching.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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// Linear Search - O(n)
function linearSearch(arr, val){
for(var i = 0; i < arr.length; i++){
if(arr[i] === val) return i;
}
return -1;
}
linearSearch([34,51,1,2,3,45,56,687], 100)
// Binary Search - O( log(n) )
// Binary search is a much faster form of search
// Rather than eliminating one element at a time, you can eliminate half of the remaining elements at a time (Divide and Conquer)
// Binary search only works on sorted arrays!
function binarySearch(arr, ele) {
let start = 0;
let end = arr.length -1
let middle = Math.floor((start + end) / 2)
while(arr[middle] !== ele && start <= end) {
if(ele > arr[middle]) {
start = middle + 1
} else if (ele < arr[middle]) {
end = middle - 1
}
middle = Math.floor((start + end) / 2)
}
if( arr[middle] === ele) {
return middle
} else {
return -1
}
}
// const binarySearch = (nums, target) => {
// let left = 0;
// let right = nums.length - 1;
// while (left <= right) {
// const mid = Math.floor((left + right) / 2);
// const foundVal = nums[mid];
// if (foundVal === target) {
// return mid;
// } else if (foundVal < target) {
// left = mid + 1;
// } else {
// right = mid - 1;
// }
// }
//
// return null;
// };
console.log(binarySearch([1, 2, 3, 4, 5, 6, 7, 8, 9, 100], 10))
// Recursive
function binarySearchRecursive(arr, ele, left=0, right=arr.length-1) {
if(left > right) {
return -1
}
const midPoint = Math.floor((left + right) / 2)
if(arr[midPoint] === ele) {
return midPoint
}
if(ele > arr[midPoint]) {
return binarySearch(arr, ele, midPoint + 1, right)
}
if(num < arr[midPoint]) {
return binarySearch(arr, ele, left, midPoint -1)
}
}
// naive algorithm or approach, )(n*m)
function subStrSearch(long, short){
// saalik
// ali
let matches = {}
for(let i = 0; i < long.length; i++) {
for(let j = 0; j < short.length; j++) {
if (short[j] !== long[i+j]) {
break
}
if(j === short.length - 1) {
matches[short] = (matches[short] || 0) + 1
}
}
}
return matches
}
console.log(subStrSearch("there are many students there", "re"))
// Building the Table
function matchTable(word) {
let arr = Array.from({ length: word.length }).fill(0);
let suffixEnd = 1;
let prefixEnd = 0;
while (suffixEnd < word.length) {
if (word[suffixEnd] === word[prefixEnd]) {
// we can build a longer prefix based on this suffix
// store the length of this longest prefix
// move prefixEnd and suffixEnd
prefixEnd += 1;
arr[suffixEnd] = prefixEnd;
suffixEnd += 1;
} else if (word[suffixEnd] !== word[prefixEnd] && prefixEnd !== 0) {
// there's a mismatch, so we can't build a larger prefix
// move the prefixEnd to the position of the next largest prefix
prefixEnd = arr[prefixEnd - 1];
} else {
// we can't build a proper prefix with any of the proper suffixes
// let's move on
arr[suffixEnd] = 0;
suffixEnd += 1;
}
}
return arr;
}
// KMP Algorithm - O(n + m) time, O(m) space
// KMP provides a linear time algorithm for searches in strings
function kmpSearch(long, short) {
let table = matchTable(short);
let shortIdx = 0;
let longIdx = 0;
let count = 0;
while (longIdx < long.length - short.length + shortIdx + 1) {
if (short[shortIdx] !== long[longIdx]) {
// we found a mismatch :(
// if we just started searching the short, move the long pointer
// otherwise, move the short pointer to the end of the next potential prefix
// that will lead to a match
if (shortIdx === 0) longIdx += 1;
else shortIdx = table[shortIdx - 1];
} else {
// we found a match! shift both pointers
shortIdx += 1;
longIdx += 1;
// then check to see if we've found the substring in the large string
if (shortIdx === short.length) {
// we found a substring! increment the count
// then move the short pointer to the end of the next potential prefix
count++;
shortIdx = table[shortIdx - 1];
}
}
}
return count;
}