-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy path0028--find-the-index-of-the-first-occurrence-in-a-string.js
234 lines (219 loc) · 7.47 KB
/
0028--find-the-index-of-the-first-occurrence-in-a-string.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
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
// 28. Find the Index of the First Occurrence in a String
// https://leetcode.com/problems/find-the-index-of-the-first-occurrence-in-a-string/
// Medium
//
// My Solution on LeetCode:
// https://leetcode.com/problems/find-the-index-of-the-first-occurrence-in-a-string/solutions/3253386/javascript-php-6-solutions-with-explanation-simple-and-understandable/
//
// Given two strings needle and haystack, return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
//Example 1:
//Input: haystack = "sadbutsad", needle = "sad"
//Output: 0
//Explanation: "sad" occurs at index 0 and 6.
//The first occurrence is at index 0, so we return 0.
//Example 2:
//Input: haystack = "leetcode", needle = "leeto"
//Output: -1
//Explanation: "leeto" did not occur in "leetcode", so we return -1.
//
//Constraints:
//1 <= haystack.length, needle.length <= 104
//haystack and needle consist of only lowercase English characters.
//
// STRING MATCHING ALGORITHMS
// http://www-igm.univ-mlv.fr/~lecroq/string/index.html
// Solution #1 - Built-in function strpos()
// Use the strpos() Built-in function to find the position of the substring in the string. If the substring is not found, return -1.
//
// Solution #2 - Find Substring Position with Regex
// Create a pattern based on the needle and use preg_match() function to compare the haystack and needle and return the index position. If the substring is not found, return -1.
//
// Solution #3 - Brute Force
// Loop through the haystack. For each character, loop through the needle and compare. If they are all equal, return the index of the haystack
//
// Solution #4 - Brute Force Substring Search
// Create a loop to iterate through the haystack and compare the substrings of the haystack and needle using the substr() function. Return the index position of the needle or -1 if not found.
//
// Solution #5 - Tracking Loop Search - Time: O(N), Space: O(1)
// Loop through the haystack string and compare each character of the substring to the corresponding character in the haystack. If all characters match, the index is returned. If the substring is not found, return -1.
//
// Solution #6 - KMP - Time: O(N+M) | KMP - Knuth-Morris-Pratt String Matching Algorithm
// Preprocess the needle to form an array to store the occurs before.
// Loop through the haystack and compare with needle. If mismatch occurs, move the haystack index by the occurs before array.
// https://en.wikipedia.org/wiki/Knuth–Morris–Pratt_algorithm
//
/**
* Solution #1 - Built-in function
*
* @param {string} haystack
* @param {string} needle
* @return {number}
*/
var strStr = function (haystack, needle) {
return haystack.indexOf(needle);
};
/**
* Solution #2 - RegExp
*
* @param {string} haystack
* @param {string} needle
* @return {number}
*/
var strStr = function (haystack, needle) {
const regex = new RegExp(needle);
return haystack.search(regex);
};
/**
* Solution #3 - Brute Force - Time: O(N*M), Space: O(1)
* Loop through the haystack. For each character, loop through the needle and compare.
* If they are all equal, return the index of the haystack
*
* @param {string} haystack
* @param {string} needle
* @return {number}
*/
var strStr = function (haystack, needle) {
if (!needle) return 0;
for (let i = 0; i < haystack.length; i++) {
let isMatch = true;
for (let j = 0; j < needle.length; j++) {
if (haystack[i + j] !== needle[j]) {
isMatch = false;
break;
}
}
if (isMatch) return i;
}
return -1;
};
/**
* Solution #4 - Loop through haystack and compare substrings - Time: O(N), Space: O(1)
* Loop through the haystack. For each character, loop through the needle and compare.
* If they are all equal, return the index of the haystack
*
* @param {string} haystack
* @param {string} needle
* @return {number}
*/
var strStr = function (haystack, needle) {
let haystackLength = haystack.length;
let needleLength = needle.length;
if (haystackLength < needleLength) return -1;
for (let i = 0; i <= haystackLength - needleLength; i++) {
if (haystack.substr(i, needleLength) === needle) return i;
}
return -1;
};
/**
* Solution #5 - Loop through haystack and compare characters one by one - Time: O(N), Space: O(1)
* Loop through the haystack string and compare each character of the substring to the corresponding character in the haystack. If all characters match, the index is returned. If the substring is not found, return -1.
*
* @param {string} haystack
* @param {string} needle
* @return {number}
*/
var strStr = function (haystack, needle) {
let haystackLength = haystack.length;
let needleLength = needle.length;
if (haystackLength < needleLength) return -1;
let matchingIndex = 0;
for (let i = 0; i < haystackLength; i++) {
if (needle[i - matchingIndex] !== haystack[i]) {
i = matchingIndex;
matchingIndex = i + 1;
} else if (i - matchingIndex == needleLength - 1) {
return matchingIndex;
}
}
return -1;
};
/**
* Solution #6: KMP - Time: O(N+M) | KMP - Knuth-Morris-Pratt String Matching Algorithm
* Preprocess the needle to form an array to store the occurs before.
* Loop through the haystack and compare with needle.
* If mismatch occurs, move the haystack index by the occurs before array.
*
* Explanation
* https://www.youtube.com/watch?v=JoF0Z7nVSrA
*
* @param {string} haystack
* @param {string} needle
* @return {number}
*/
var strStr = function (haystack, needle) {
const needleLength = needle.length;
let i = 0, j = -1;
// LPS - Longest Prefix Suffix / Prefix table https://iq.opengenus.org/prefix-table-lps/
const lps = [-1];
while (i < needleLength - 1) {
if (j === -1 || needle[i] === needle[j]) {
i++;
j++;
lps[i] = j;
} else {
j = lps[j];
}
}
i = 0, j = 0;
while (i < haystack.length && j < needleLength) {
if (haystack[i] === needle[j]) {
i++;
j++;
} else {
j = lps[j];
if (j < 0) {
i++;
j++;
}
}
}
if (j === needleLength) {
return i - j;
}
return -1;
}
//
//
// var strStr = function (haystack, needle) {
// let haystackLength = haystack.length;
// let needleLength = needle.length;
// if (needleLength === 0) return 0;
// if (haystackLength < needleLength) return -1;
//
// // LPS - Longest Prefix Suffix / Prefix table https://iq.opengenus.org/prefix-table-lps/
// let lps = [];
// for (let i = 0; i < needleLength; i++) lps.push(0);
// let prevLPS = 0;
// let i = 1;
// while (i < needleLength) {
// if (needle[i] === needle[prevLPS]) {
// lps[i] = prevLPS + 1;
// prevLPS++;
// i++;
// } else if (prevLPS === 0) {
// lps[i] = 0;
// i++;
// } else {
// prevLPS = lps[prevLPS - 1];
// }
// }
//
// i = 0; // for haystack
// j = 0; // for needle
// while (i < haystackLength) {
// if (haystack[i] === needle[j]) {
// i++;
// j++;
// } else {
// if (j === 0) {
// i++;
// } else {
// j = lps[j - 1];
// }
// }
// if (j === needleLength) {
// return i - needleLength;
// }
// }
// return -1;
// };