You are attempting to find the index of the first appearance of one string (the needle) inside of another (the haystack).
indexOf('or', 'hello world'); // should return 7
indexOf('hello world', 'or'); // should return -1
indexOf('howdy', 'hello world'); // should return -1
indexOf('oox', 'ooboxoooxo'); // should return 6
split() and loop
-
Most students also move to split the haystack into an array of characters, and then loop through.
-
This approach would work; but imagine the space complexity of generating a new array and then holding it in memory for a very, very large haystack. You would be introducing another O(n) dimension in time and space, where n is the length of the haystack.
-
If they're in a groove, have them finish out this approach and pseudocode it; then ask them how they would do this without generating a second copy of the haystack.
function indexOf(needle, haystack) {
for (let hIdx = 0; hIdx <= haystack.length - needle.length; hIdx++) {
for (let nIdx = 0; nIdx < needle.length; nIdx++) {
if (haystack[hIdx + nIdx] !== needle[nIdx]) break;
if (nIdx + 1 === needle.length) return hIdx;
}
}
return -1;
}
Where n is the haystack size and m the needle size, the solution is O(n*m).
Why?
function indexOf(needle, haystack) {
for (let hIdx = 0; hIdx <= haystack.length - needle.length; hIdx++) {
//O(n * ...) where n is the number of letters in haystack
for (let nIdx = 0; nIdx < needle.length; nIdx++) {
//O(m * ...) where m is the number of letters in needle
if (haystack[hIdx + nIdx] !== needle[nIdx]) break;
//O(1) constant
if (nIdx + 1 === needle.length) return hIdx;
//O(1) constant
}
}
return -1;
O(1); // constant
}
So, O(n * (m * (1 + 1)))=> O(n*m)