Find the Occurrence of First Almost Equal Substring
HardPrompt
You are given two strings s and pattern.
A string x is called almost equal to y if you can change at most one character in x to make it identical to y.
Return the smallest starting index of a substring in s that is almost equal to pattern. If no such index exists, return -1.
Example 1:
Input: s = "abcdefg", pattern = "bcdffg"
Output: 1
Explanation:
The substring s[1..6] == "bcdefg" can be converted to "bcdffg" by changing s[4] to "f".
Example 2:
Input: s = "ababbababa", pattern = "bacaba"
Output: 4
Explanation:
The substring s[4..9] == "bababa" can be converted to "bacaba" by changing s[6] to "c".
Example 3:
Input: s = "abcd", pattern = "dba"
Output: -1
Example 4:
Input: s = "dde", pattern = "d"
Output: 0
Constraints:
1 <= pattern.length < s.length <= 105sandpatternconsist only of lowercase English letters.
Follow-up: Could you solve the problem if at most
k consecutive characters can be changed?Approaches
3 approaches with complexity analysis and trade-offs.
The brute-force approach is the most straightforward way to solve the problem. It involves checking every possible substring of s that has the same length as pattern. For each of these substrings, we compare it character by character with pattern to count the number of differing characters. If the count is less than or equal to one, we have found a valid substring, and since we are iterating from the beginning, the first one we find will be at the smallest starting index.
Algorithm
- Get the lengths of
sandpattern, let them benandm. - Iterate with an index
ifrom0ton - m. Thisirepresents the starting index of a potential substring ins. - For each
i, create a nested loop with indexjfrom0tom-1to compare the substrings[i...i+m-1]withpattern. - Maintain a
difference_countfor each window, initialized to0. - In the inner loop, if
s.charAt(i + j)is not equal topattern.charAt(j), incrementdifference_count. - If
difference_countexceeds1, break the inner loop and proceed to the next starting indexi, as this window is not a valid candidate. - After the inner loop completes, if
difference_countis0or1, it means we have found the first almost equal substring. Return the starting indexi. - If the outer loop finishes without finding any such substring, return
-1.
Walkthrough
This method iterates through all possible starting positions for a substring in s that matches the length of pattern. For each position, it performs a direct character-by-character comparison against pattern.
- Algorithm Steps:
- Get the lengths of
sandpattern, let them benandm. - Iterate with an index
ifrom0ton - m. Thisirepresents the starting index of a potential substring ins. - For each
i, create a nested loop with indexjfrom0tom-1to compare the substrings[i...i+m-1]withpattern. - Maintain a
difference_countfor each window, initialized to0. - In the inner loop, if
s.charAt(i + j)is not equal topattern.charAt(j), incrementdifference_count. - If
difference_countexceeds1, break the inner loop and proceed to the next starting indexi, as this window is not a valid candidate. - After the inner loop completes, if
difference_countis0or1, it means we have found the first almost equal substring. Return the starting indexi. - If the outer loop finishes without finding any such substring, return
-1.
class Solution { public int firstAlmostEqual(String s, String pattern) { int n = s.length(); int m = pattern.length(); if (n < m) { return -1; } for (int i = 0; i <= n - m; i++) { int diff = 0; for (int j = 0; j < m; j++) { if (s.charAt(i + j) != pattern.charAt(j)) { diff++; if (diff > 1) { break; // Optimization to exit early } } } if (diff <= 1) { return i; } } return -1; }}Complexity
Time
O(N * M) - Where N is the length of `s` and M is the length of `pattern`. The outer loop runs `N - M + 1` times, and the inner loop runs `M` times.
Space
O(1) - We only use a few variables to store lengths and counts, which does not depend on the input size.
Trade-offs
Pros
Simple to understand and implement.
Requires no extra space, making it very memory efficient.
Cons
Highly inefficient for large strings.
Leads to a 'Time Limit Exceeded' (TLE) error on platforms with strict time constraints for the given input sizes.
Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.