You are given a potentially infinite stream of characters arriving one at a time. You are also given a specific pattern (a string) that you need to detect within this stream.
Design an algorithm to efficiently detect the presence of the pattern in the stream. You should output true as soon as the pattern is detected, and false otherwise. Assume you can only store a limited number of characters from the stream at any given time.
Example 1:
Stream: a b a b c a b a a b c a b a b
Pattern: a b a b
Output: true
Explanation: "a b a b" is detected at the end of the stream.
Example 2:
Stream: a b c d e f g
Pattern: a b a
Output: false
Explanation: "a b a" is not found in the stream.
Example 3:
Stream: a a a a a a a
Pattern: a a a
Output: true
Constraints:
1 and 105.When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The brute force method is like comparing the pattern against every single possible segment of the infinite stream. We painstakingly check each potential match, one after another. It's an exhaustive, but simple, way to find the pattern.
Here's how the algorithm would work step-by-step:
def find_pattern_brute_force(stream, pattern):
stream_length = len(stream)
pattern_length = len(pattern)
for stream_index in range(stream_length - pattern_length + 1):
# Check if the pattern matches the stream at this starting index
pattern_matched = True
for pattern_index in range(pattern_length):
if stream[stream_index + pattern_index] != pattern[pattern_index]:
pattern_matched = False
break
# If a complete match is found, return True
if pattern_matched:
return True
# If the entire stream is exhausted without finding a match
# then the pattern does not exist in the stream
return FalseThe best way to find a pattern in a never-ending stream is to remember only what's necessary. We'll keep track of the pattern we are searching for and, as we look at each new piece of the stream, we will update our understanding of how much of the pattern we've seen so far.
Here's how the algorithm would work step-by-step:
def find_pattern_in_stream(stream, pattern):
pattern_length = len(pattern)
chars_matched = 0
for stream_char in stream:
# Check if current stream char matches the next pattern char
if stream_char == pattern[chars_matched]:
chars_matched += 1
# Entire pattern found, reset for further matches
if chars_matched == pattern_length:
return True
else:
# Check if stream char matches the beginning of pattern
if stream_char == pattern[0]:
chars_matched = 1
# Reset match if stream char doesn't start pattern
else:
chars_matched = 0
return False| Case | How to Handle |
|---|---|
| Null input stream | Throw an IllegalArgumentException or return an empty list, depending on requirements. |
| Empty input stream | Return an empty list, as no pattern can be found in an empty stream. |
| Pattern is larger than the initially available stream data | Buffer enough data to accommodate the full pattern length before processing. |
| Very long stream with frequent, but slightly altered, near-matches to the pattern | Ensure efficient pattern matching algorithm to avoid quadratic time complexity in near match cases. |
| Pattern contains special characters or delimiters relevant to stream reading | Escape or handle these characters appropriately during stream processing and pattern matching. |
| Pattern occurs at the very beginning of the infinite stream | The matching algorithm should be able to find the pattern starting from the stream's first element. |
| Pattern never occurs in the infinite stream | Implement a mechanism to terminate the search after a reasonable time or data limit is reached and return an appropriate result (e.g., null or empty list). |
| Stream reading errors | Implement error handling to catch and log any exceptions that might occur while reading from the stream. |