Existence of a Substring in a String and Its Reverse solution and explanation
7 more videos on this problem
Leetcode | 3083. Existence of a Substring in a String and Its Reverse | Easy | Java SolutionDeveloper Docs · 2:57 · 648 views
3083. Existence of a Substring in a String and Its Reverse (Leetcode Easy)Programming Live with Larry · 2:55 · 436 views
Leetcode # 3083 Existence of a Substring in a String and Its Reverse (Python)Sumanshu Nankana · 7:15 · 268 views
3083: Substring Existence in a String and Its Reverse | Leetcode Weekly Contest - 389.CodeRebel · 8:54 · 228 views
LeetCode | 3083. Existence of a Substring in a String and Its Reverse | Easy | Weekly Contest 389Coding with Bobby · 7:18 · 178 views
🏁Weekly Contest 389 is Here ! Problem 1- 3083. Existence of a Substring in a String and Its ReverseAchyuth Chowdary · 4:07 · 59 views
Existence of a Substring in a String and Its Reverse | Leetcode 3083 | Weekly Contest 389 SolutionAman Baluni · 2:57 · 53 views
Leetcode Weekly Contest 389 || 3083. Existence of a Substring in a String and Its Reverse ||Nonu_ke_funs😂 · 16:48 · 11 views
The problem
Given a string s, find any substring of length 2 which is also present in the reverse of s.
Return true if such a substring exists, and false otherwise.
Example 1:
Input: s = "leetcode"
Output: true
Explanation: Substring "ee" is of length 2 which is also present in reverse(s) == "edocteel".
Example 2:
Input: s = "abcba"
Output: true
Explanation: All of the substrings of length 2 "ab", "bc", "cb", "ba" are also present in reverse(s) == "abcba".
Example 3:
Input: s = "abcd"
Output: false
Explanation: There is no substring of length 2 in s, which is also present in the reverse of s.
Constraints:
1 <= s.length <= 100sconsists only of lowercase English letters.
Approach overview
Problem Overview: Given a string s, determine whether there exists a substring of length two such that its reverse also appears somewhere in the string. For example, if "ab" exists and "ba" also exists, the answer is true. The task is essentially detecting mirrored two‑character patterns inside the same string.
Approach 1: Using Sorting (O(n log n) time, O(n) space)
Generate all substrings of length two by iterating through the string once. Store each pair in an array, and also generate their reversed forms. Sorting both collections allows you to efficiently compare them and detect whether any pair matches its reversed counterpart. After sorting, you can scan with two pointers or binary search to find intersections between the substring list and reversed substring list.
This approach relies on ordering rather than constant-time lookups. The key idea is that once substrings are sorted, equal strings become adjacent, making matches easy to detect. Time complexity becomes O(n log n) due to sorting, and the auxiliary storage for substrings requires O(n) space. While not optimal, it demonstrates a straightforward transformation of a string problem into a searchable dataset.
Approach 2: Using Hashing (O(n) time, O(n) space)
Iterate through the string and extract every substring of length two. Insert each substring into a hash set. For every pair s[i]s[i+1], compute its reverse s[i+1]s[i] and check if it already exists in the set. A constant-time hash lookup immediately tells you whether the reversed pattern has appeared earlier.
The insight is that the substring length is fixed at two. That allows fast generation and constant-time membership checks with a hash table. Each step performs simple operations: substring creation, reversal, and hash lookup. The entire scan runs in linear time O(n) with O(n) space for storing seen substrings.
This method is the standard solution used in most editorial explanations. It avoids sorting overhead and uses direct lookups, which is ideal for short substring matching problems commonly seen in string and hash-table interview questions.
Recommended for interviews: The hashing approach. It shows you recognize fixed-length substring patterns and can reduce the problem to constant-time lookups. Mentioning the sorting method can demonstrate baseline reasoning, but interviewers expect the O(n) hash-set solution because it minimizes both logic complexity and runtime.
Approach 1: Approach 1: Using Sorting
This approach involves sorting the array first, then using a two-pointer technique to solve the problem. By sorting, we can utilize the sorted order to efficiently find pairs or triplets that meet our requirements.
def find_pair(arr, target):
arr.sort()
left, right = 0, len(arr) - 1
while left < right:
current_sum = arr[left] + arr[right]
if current_sum == target:
print(f"Pair found: ({arr[left]}, {arr[right]})")
return
elif current_sum < target:
left += 1
else:
right -= 1
print("No pair found")
arr = [8, 7, 2, 5, 3, 1]
target = 10
find_pair(arr, target)import java.util.Arrays;
public class PairFinder {
public static void findPair(int[] arr, int target) {
Arrays.sort(arr);
int left = 0, right = arr.length - 1;
while (left < right) {
int sum = arr[left] + arr[right];
if (sum == target) {
System.out.println("Pair found: (" + arr[left] + ", " + arr[right] + ")");
return;
} else if (sum < target) {
left++;
} else {
right--;
}
}
System.out.println("No pair found");
}
public static void main(String[] args) {
int[] arr = {8, 7, 2, 5, 3, 1};
int target = 10;
findPair(arr, target);
}
}#include <iostream>
#include <algorithm>
using namespace std;
void findPair(int arr[], int n, int target) {
sort(arr, arr + n);
int left = 0, right = n - 1;
while (left < right) {
int sum = arr[left] + arr[right];
if (sum == target) {
cout << "Pair found: (" << arr[left] << ", " << arr[right] << ")\n";
return;
} else if (sum < target) {
left++;
} else {
right--;
}
}
cout << "No pair found\n";
}
int main() {
int arr[] = {8, 7, 2, 5, 3, 1};
int target = 10;
int n = sizeof(arr) / sizeof(arr[0]);
findPair(arr, n, target);
return 0;
}function findPair(arr, target) {
arr.sort((a, b) => a - b);
let left = 0, right = arr.length - 1;
while (left < right) {
const sum = arr[left] + arr[right];
if (sum === target) {
console.log(`Pair found: (${arr[left]}, ${arr[right]})`);
return;
} else if (sum < target) {
left++;
} else {
right--;
}
}
console.log("No pair found");
}
const arr = [8, 7, 2, 5, 3, 1];
const target = 10;
findPair(arr, target);#include <stdio.h>
#include <stdlib.h>
void findPair(int arr[], int n, int target) {
qsort(arr, n, sizeof(int), compare);
int left = 0, right = n - 1;
while (left < right) {
int sum = arr[left] + arr[right];
if (sum == target) {
printf("Pair found: (%d, %d)\n", arr[left], arr[right]);
return;
} else if (sum < target) {
left++;
} else {
right--;
}
}
printf("No pair found\n");
}
int compare(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
int main() {
int arr[] = {8, 7, 2, 5, 3, 1};
int target = 10;
int n = sizeof(arr) / sizeof(arr[0]);
findPair(arr, n, target);
return 0;
}using System;
class Program {
public static void FindPair(int[] arr, int target) {
Array.Sort(arr);
int left = 0, right = arr.Length - 1;
while (left < right) {
int sum = arr[left] + arr[right];
if (sum == target) {
Console.WriteLine("Pair found: (" + arr[left] + ", " + arr[right] + ")");
return;
} else if (sum < target) {
left++;
} else {
right--;
}
}
Console.WriteLine("No pair found");
}
static void Main() {
int[] arr = {8, 7, 2, 5, 3, 1};
int target = 10;
FindPair(arr, target);
}
}The Python code uses the built-in sorting function arr.sort() for ease and clarity. We then apply the two-pointer technique by iterating over indices to check summation against the target.
Time Complexity: O(n log n) due to the sorting operation.
Space Complexity: O(1) because the sort is in-place.
Approach 2: Approach 2: Using Hashing
In this approach, a hash map (or dictionary) is used to keep track of the elements we have seen so far and their respective indices. This allows for efficient look-up to find pairs that sum to the target value without needing to sort the array.
def find_pair(arr, target):
hash_map = {}
for i, num in enumerate(arr):
complement = target - num
if complement in hash_map:
print(f"Pair found: ({num}, {complement})")
return
hash_map[num] = i
print("No pair found")
arr = [8, 7, 2, 5, 3, 1]
target = 10
find_pair(arr, target)import java.util.HashMap;
public class PairFinderHash {
public static void findPair(int[] arr, int target) {
HashMap<Integer, Integer> hashMap = new HashMap<>();
for (int i = 0; i < arr.length; i++) {
int complement = target - arr[i];
if (hashMap.containsKey(complement)) {
System.out.println("Pair found: (" + arr[i] + ", " + complement + ")");
return;
}
hashMap.put(arr[i], i);
}
System.out.println("No pair found");
}
public static void main(String[] args) {
int[] arr = {8, 7, 2, 5, 3, 1};
int target = 10;
findPair(arr, target);
}
}#include <iostream>
#include <unordered_map>
using namespace std;
void findPair(int arr[], int n, int target) {
unordered_map<int, int> hashMap;
for (int i = 0; i < n; i++) {
int complement = target - arr[i];
if (hashMap.find(complement) != hashMap.end()) {
cout << "Pair found: (" << arr[i] << ", " << complement << ")\n";
return;
}
hashMap[arr[i]] = i;
}
cout << "No pair found\n";
}
int main() {
int arr[] = {8, 7, 2, 5, 3, 1};
int target = 10;
int n = sizeof(arr) / sizeof(arr[0]);
findPair(arr, n, target);
return 0;
}function findPair(arr, target) {
const hashMap = new Map();
for (let i = 0; i < arr.length; i++) {
const complement = target - arr[i];
if (hashMap.has(complement)) {
console.log(`Pair found: (${arr[i]}, ${complement})`);
return;
}
hashMap.set(arr[i], i);
}
console.log("No pair found");
}
const arr = [8, 7, 2, 5, 3, 1];
const target = 10;
findPair(arr, target);#include <stdio.h>
#include <stdlib.h>
#define TABLE_SIZE 100
typedef struct Entry {
int key;
int value;
} Entry;
Entry* hashTable[TABLE_SIZE];
unsigned int hash(int key) {
return key % TABLE_SIZE;
}
void insert(int key, int value) {
Entry* entry = (Entry*) malloc(sizeof(Entry));
entry->key = key;
entry->value = value;
hashTable[hash(key)] = entry;
}
Entry* search(int key) {
return hashTable[hash(key)];
}
void findPair(int arr[], int n, int target) {
for (int i = 0; i < n; i++) {
int complement = target - arr[i];
Entry* entry = search(complement);
if (entry && entry->key == complement) {
printf("Pair found: (%d, %d)\n", arr[i], complement);
return;
}
insert(arr[i], i);
}
printf("No pair found\n");
}
int main() {
int arr[] = {8, 7, 2, 5, 3, 1};
int target = 10;
int n = sizeof(arr) / sizeof(arr[0]);
findPair(arr, n, target);
return 0;
}using System;
using System.Collections.Generic;
class Program {
public static void FindPair(int[] arr, int target) {
Dictionary<int, int> hashMap = new Dictionary<int, int>();
for (int i = 0; i < arr.Length; i++) {
int complement = target - arr[i];
if (hashMap.ContainsKey(complement)) {
Console.WriteLine("Pair found: (" + arr[i] + ", " + complement + ")");
return;
}
hashMap[arr[i]] = i;
}
Console.WriteLine("No pair found");
}
static void Main() {
int[] arr = {8, 7, 2, 5, 3, 1};
int target = 10;
FindPair(arr, target);
}
}For Python, we use a dictionary to track elements and their indices. By checking for the complement before insertion, we ensure we find the pair, if it exists, in optimal time.
Time Complexity: O(n) on average.
Space Complexity: O(n) for the dictionary storage.
Approach 3: Hash Table or Array
We can use a hash table or a two-dimensional array st to store all substrings of length 2 of the reversed string s.
Then we traverse the string s. For each substring of length 2, we check whether it has appeared in st. If it has, we return true. Otherwise, we return false after the traversal.
The time complexity is O(n) and the space complexity is O(|\Sigma|^2). Here, n is the length of the string s, and \Sigma is the character set of the string s. In this problem, \Sigma consists of lowercase English letters, so |\Sigma| = 26.
function isSubstringPresent(s: string): boolean {
const st: boolean[][] = Array.from({ length: 26 }, () => Array(26).fill(false));
for (let i = 0; i < s.length - 1; ++i) {
st[s.charCodeAt(i + 1) - 97][s.charCodeAt(i) - 97] = true;
}
for (let i = 0; i < s.length - 1; ++i) {
if (st[s.charCodeAt(i) - 97][s.charCodeAt(i + 1) - 97]) {
return true;
}
}
return false;
}func isSubstringPresent(s string) bool {
st := [26][26]bool{}
for i := 0; i < len(s)-1; i++ {
st[s[i+1]-'a'][s[i]-'a'] = true
}
for i := 0; i < len(s)-1; i++ {
if st[s[i]-'a'][s[i+1]-'a'] {
return true
}
}
return false
}Complexity comparison
| Approach | Complexity |
|---|---|
| Approach 1: Using Sorting | Time Complexity: O(n log n) due to the sorting operation. |
| Approach 2: Using Hashing | Time Complexity: O(n) on average. |
| Hash Table or Array | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Sorting substrings | O(n log n) | O(n) | When converting substring comparisons into sorted datasets or when practicing sorting-based matching techniques |
| Hash set lookup | O(n) | O(n) | General case and interview settings where constant-time substring lookup is preferred |
Frequently asked questions
Is Existence of a Substring in a String and Its Reverse easy or hard?
The problem is categorized as Easy on LeetCode with an acceptance rate above 60%. It focuses on basic string iteration and hash-set usage, making it a common warm-up problem for practicing string and hash table concepts.
Existence of a Substring in a String and Its Reverse Python/Java solution
Most implementations follow the same pattern: iterate through the string, store two-character substrings in a set, and check whether the reversed pair exists. This logic translates directly across Python, Java, C++, and other languages with built-in hash set support.
How to solve Existence of a Substring in a String and Its Reverse in O(n)?
Scan the string and extract every substring of length two. Insert each substring into a hash set and check whether its reversed form already exists. Since insertion and lookup in a hash table are constant time on average, the entire process completes in linear O(n) time.
What is the best approach for Existence of a Substring in a String and Its Reverse?
The most efficient approach uses a hash set. Iterate through the string, store every substring of length two, and check whether the reversed pair already exists in the set. This gives O(n) time complexity with O(n) extra space and is the solution typically expected in coding interviews.
Is Existence of a Substring in a String and Its Reverse asked at Google/Amazon/Meta?
Problems like this appear frequently in interviews at large tech companies because they test string traversal and hash-table usage. While this exact problem is from LeetCode, similar substring detection and pattern-matching questions show up in interviews at companies like Amazon, Google, and Meta.
What data structure is used in Existence of a Substring in a String and Its Reverse?
A hash set (or hash table) is the primary data structure used in the optimal solution. It stores previously seen substrings and enables constant-time checks to determine whether the reverse of the current substring already exists.
What is the time complexity of Existence of a Substring in a String and Its Reverse?
The optimal hash-set approach runs in O(n) time because the string is scanned once and each substring lookup is O(1). Space complexity is O(n) for storing substrings. A sorting-based method exists but increases the time complexity to O(n log n).
