The Problem Statement
Given: An array of strings. Task: Write a function to find the longest common prefix string amongst all the strings in the array. If there is no common prefix, return an empty string "".
Example:
- Input:
strs = ["flower", "flow", "flight"] - Output:
"fl" - Input:
strs = ["dog", "racecar", "car"] - Output:
""(No common prefix exists)
Approach 1: Horizontal Scanning (The Standard Way)
Intuition
Think of this like finding the common denominator. You take the first string and assume it's the longest common prefix. Then, you compare it with the second string and chop off characters from the end of your prefix until it matches the beginning of the second string. You repeat this updated prefix against the third string, and so on.
Algorithm
- If the array is empty, return
"". - Initialize
prefixwith the first stringstrs[0]. - Loop through the remaining strings from index to .
- For each string, check if it starts with the
prefix. - If it doesn't, remove the last character from
prefixand check again. - If
prefixbecomes empty at any point, return"". - Return
prefixafter the loop completes.
c++ code:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
string longestCommonPrefixHorizontal(vector<string>& strs) {
if (strs.empty()) return "";
string prefix = strs[0];
for (int i = 1; i < strs.size(); i++) {
// while strs[i] doesn't start with the prefix
while (strs[i].find(prefix) != 0) {
// shorten the prefix by 1 character from the end
prefix = prefix.substr(0, prefix.length() - 1);
if (prefix.empty()) return "";
}
}
return prefix;
}Dry run:
Complexity Analysis
- Time Complexity: , where is the sum of all characters in all strings. In the worst case, all strings are identical.
- Space Complexity: . We only use constant extra space to store the prefix pointer.
Approach 2: Vertical Scanning (The Fail-Fast Way)
Intuition
Instead of comparing whole strings horizontally, look at the array column by column. Check the character of every string. If they all match, check the character, and so on. This approach is superior when there is a very short string at the very end of the array, preventing you from needlessly processing long strings at the beginning.
Algorithm
- If the array is empty, return
"". - Iterate through the characters of the first string
strs[0]using indexi. - For each character, iterate through the rest of the strings
strs[j]. - If
iequals the length ofstrs[j](meaning we've reached the end of a string) OR if the characterstrs[j][i]doesn't matchstrs[0][i], return the substring ofstrs[0]up toi. - If the loop completes, the entire first string is the common prefix.
C++ Code
#include <iostream>
#include <vector>
#include <string>
using namespace std;
string longestCommonPrefixVertical(vector<string>& strs) {
if (strs.empty()) return "";
for (int i = 0; i < strs[0].length(); i++) {
char c = strs[0][i];
for (int j = 1; j < strs.size(); j++) {
// Check for mismatch or if we've reached the end of the current string
if (i == strs[j].length() || strs[j][i] != c) {
return strs[0].substr(0, i);
}
}
}
return strs[0];
}Dry Run:
Complexity Analysis
- Time Complexity: in the worst case (all strings are identical). However, in the best case (where the very first character mismatches), it's where is the number of strings.
- Space Complexity: . Constant extra space used.
Approach 3: Sorting (The Elegant Trick)
Intuition
If you sort an array of strings lexicographically (alphabetically), the strings that share the least common prefix will end up at the extreme ends of the array. Therefore, the longest common prefix for the entire array is simply the common prefix between the first and the last string in the sorted array.
Algorithm
- Sort the array of strings.
- Grab the first string
strs[0]and the last stringstrs[N-1]. - Compare them character by character.
- Stop when characters differ or you reach the end of the shorter string.
- Return the matched portion.
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
string longestCommonPrefixSorting(vector<string>& strs) {
if (strs.empty()) return "";
// Sort the array lexicographically
sort(strs.begin(), strs.end());
string first = strs.front();
string last = strs.back();
int i = 0;
// Compare first and last strings
while (i < first.length() && i < last.length() && first[i] == last[i]) {
i++;
}
return first.substr(0, i);
}Dry Run
Input: ["flower", "flow", "flight"]
- Sort:
["flight", "flow", "flower"] - First string:
"flight" - Last string:
"flower" - Compare:
- Index 0:
f==f - Index 1:
l==l - Index 2:
i!=o. Mismatch.
- Index 0:
- Result: Substring of
"flight"up to index 2"fl"
Complexity Analysis
- Time Complexity: , where is the number of strings and is the maximum length of a string. String comparison takes time, and sorting items takes comparisons. While technically slower theoretically than , standard library sorts are highly optimized and it runs incredibly fast in practice.
- Space Complexity: or depending on the language's sorting algorithm implementation (C++
std::sortuses Introsort, which requires stack space).
Interview & OA Tips
- Watch the Hidden Test Cases: Online assessments are notorious for edge cases. Always explicitly handle
strs.empty() == trueorstrs = [""]. Missing these will cause a segfault or out-of-bounds error on hidden tests. - Start with Vertical Scanning: If asked to code this live, Vertical Scanning is often the most robust answer because it demonstrates you understand how to avoid unnecessary work (failing fast if a mismatch is found early).
- Use the Sorting Approach as a "Flex": If you solve it quickly with horizontal/vertical scanning, mention the sorting approach as a cool optimization alternative. It shows strong algorithmic thinking and deep familiarity with lexicographical properties.
- Discuss Trade-offs: Be ready to answer: "Which approach is better?"
- If the array has millions of strings but the mismatch happens on the 2nd character: Vertical Scanning is best.
- If the strings are incredibly long and mostly identical: Horizontal Scanning is highly cache-friendly.
code link:
https://leetcode.com/problems/longest-common-prefix/description/
video reference:
