forked from billryan/algorithm-exercise
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
133 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
# strStr | ||
|
||
## Question | ||
|
||
- leetcode: [Implement strStr() | LeetCode OJ](https://leetcode.com/problems/implement-strstr/) | ||
- lintcode: [lintcode - (13) strstr](http://www.lintcode.com/en/problem/strstr/) | ||
|
||
### Problem Statement | ||
|
||
For a given source string and a target string, you should output the **first** | ||
index(from 0) of target string in source string. | ||
|
||
If target does not exist in source, just return `-1`. | ||
|
||
#### Example | ||
|
||
If source = `"source"` and target = `"target"`, return `-1`. | ||
|
||
If source = `"abcdabcdefg"` and target = `"bcd"`, return `1`. | ||
|
||
#### Challenge | ||
|
||
O(n2) is acceptable. Can you implement an O(n) algorithm? (hint: _KMP_) | ||
|
||
#### Clarification | ||
|
||
Do I need to implement KMP Algorithm in a real interview? | ||
|
||
* Not necessary. When you meet this problem in a real interview, the interviewer may just want to test your basic implementation ability. But make sure your confirm with the interviewer first. | ||
|
||
## Problem Analysis | ||
|
||
It's very straightforward to solve string match problem with nested for loops. Since we must iterate the target string, we can optimize the iteration of source string. It's unnecessary to iterate the source string if the length of remaining part does not exceed the length of target string. We can only iterate the valid part of source string. Apart from this naive algorithm, you can use a more effective algorithm such as KMP. | ||
|
||
### Python | ||
|
||
```python | ||
class Solution: | ||
def strStr(self, source, target): | ||
if source is None or target is None: | ||
return -1 | ||
|
||
for i in range(len(source) - len(target) + 1): | ||
for j in range(len(target)): | ||
if source[i + j] != target[j]: | ||
break | ||
else: # no break | ||
return i | ||
return -1 | ||
``` | ||
|
||
### C | ||
|
||
```c | ||
int strStr(char* haystack, char* needle) { | ||
if (haystack == NULL || needle == NULL) return -1; | ||
|
||
const int len_h = strlen(haystack); | ||
const int len_n = strlen(needle); | ||
for (int i = 0; i < len_h - len_n + 1; i++) { | ||
int j = 0; | ||
for (; j < len_n; j++) { | ||
if (haystack[i+j] != needle[j]) { | ||
break; | ||
} | ||
} | ||
if (j == len_n) return i; | ||
} | ||
|
||
return -1; | ||
} | ||
``` | ||
### C++ | ||
```c++ | ||
class Solution { | ||
public: | ||
int strStr(string haystack, string needle) { | ||
if (haystack.empty() && needle.empty()) return 0; | ||
if (haystack.empty()) return -1; | ||
if (needle.empty()) return 0; | ||
// in case of overflow for negative | ||
if (haystack.size() < needle.size()) return -1; | ||
for (int i = 0; i < haystack.size() - needle.size() + 1; i++) { | ||
string::size_type j = 0; | ||
for (; j < needle.size(); j++) { | ||
if (haystack[i + j] != needle[j]) break; | ||
} | ||
if (j == needle.size()) return i; | ||
} | ||
return -1; | ||
} | ||
}; | ||
``` | ||
|
||
### Java | ||
|
||
```java | ||
public class Solution { | ||
public int strStr(String haystack, String needle) { | ||
if (haystack == null && needle == null) return 0; | ||
if (haystack == null) return -1; | ||
if (needle == null) return 0; | ||
|
||
for (int i = 0; i < haystack.length() - needle.length() + 1; i++) { | ||
int j = 0; | ||
for (; j < needle.length(); j++) { | ||
if (haystack.charAt(i+j) != needle.charAt(j)) break; | ||
} | ||
if (j == needle.length()) return i; | ||
} | ||
|
||
return -1; | ||
} | ||
} | ||
``` | ||
|
||
### Source Code Analysis | ||
|
||
1. corner case: `haystack(source)` and `needle(target)` may be empty string. | ||
2. code convention: | ||
- space is needed for `==` | ||
- use meaningful variable names | ||
- put a blank line before declaration `int i, j;` | ||
3. declare j outside for loop if and only if you want to use it outside. | ||
|
||
Some Pythonic notes: [4. More Control Flow Tools](https://docs.python.org/3/tutorial/controlflow.html) section 4.4 and [if statement - Why does python use 'else' after for and while loops?](http://stackoverflow.com/questions/9979970/why-does-python-use-else-after-for-and-while-loops) | ||
|
||
### Complexity Analysis | ||
|
||
nested for loop, $$O((n-m)m)$$ for worst case. |