Longest Common Prefix
Write a function to find the longest common prefix string amongst an array of strings. If there is no common prefix, return an empty string.
- 1 <= strs.length <= 200
- 0 <= strs[i].length <= 200
- strs[i] consists of only lowercase English letters
strs = ["flower","flow","flight"]"fl"strs = ["dog","racecar","car"]""strs = ["interview","internal","interpret"]"inter"The longest common prefix is the longest run of characters that every word in the array shares, starting from position 0. The instant even one word disagrees — or simply runs out of letters — the shared prefix ends there. We return that shared run as a string, or the empty string "" when the words share nothing at the start. One bound is worth noticing immediately: the answer can never be longer than the shortest word in the array, because that word runs out of characters first.
Take the first word and treat it as a guess for the whole prefix. Compare it against the second word: if the second word does not start with the guess, chop the last character off the guess and try again, repeating until the second word does start with it. That shortened guess is now the common prefix of the first two words. Carry it forward and repeat against the third word, the fourth, and so on; if the guess ever shrinks to empty, no prefix exists and we stop.
if not strs:
return ""
prefix = strs[0]
for i in range(1, len(strs)):
while not strs[i].startswith(prefix):
prefix = prefix[:-1]
if not prefix:
return ""
return prefixThis works, but look at the wasted motion. We begin by assuming the entire first word is the prefix — possibly 200 characters — and discover how wrong we are only by peeling it back one character at a time, re-scanning from the front on each startswith check. If the true prefix is short but the first word is long, we compare deep into characters that were never going to matter. The work is driven by the first word's length, when it ought to be driven by how quickly the words start to disagree.
Stack the words on top of each other and read down the columns instead of across the rows. Column 0 is the first character of every word; column 1 is the second character of every word; and so on. A common prefix is exactly the run of columns in which all the letters agree. The moment one column holds a disagreement — or one word has no letter in that column at all — the prefix is everything in the columns before it. Framed this way, the answer reveals itself the instant the first disagreement appears, and we never read a single character past the point where the words split.
Use the first word to supply the letters to check, position by position. At each position i, look at that same position in every other word. If all of them have the same character there, the prefix extends by one. If any word differs, or any word is too short to have a character at position i, stop and return everything matched so far.
if not strs:
return ""
for i in range(len(strs[0])):
char = strs[0][i]
for j in range(1, len(strs)):
# word ran out, or the character differs
if i == len(strs[j]) or strs[j][i] != char:
return strs[0][:i]
return strs[0]i == len(strs[j]) before strs[j][i] != char — must be checked in that order, and both are load-bearing. A word can simply end while the others continue: for ["ab", "a"] the answer is "a", and at column 1 the second word has no character at all. Checking i == len(strs[j]) first catches that and returns "a"; skip it and try strs[j][1] and you index past the end of the string and crash. Short-circuiting on length before touching the character is what keeps the column scan safe.Now a case with no shared start — strs = ["dog", "racecar", "car"]:
- Column 0: guide "dog" has 'd', but "racecar" has 'r' — they disagree at the very first column. Return strs[0][:0], the empty string "". No word past the first even needs a second character read.
Both approaches are linear in the worst case, but they are driven by different things. The column scan stops at the first disagreement, so it reads at most (length of the answer + 1) characters from each of the N words — its cost is bounded by the answer's length times the number of words, never by how long the first word happens to be. When words diverge early (the common case), it barely reads anything. The shrink-the-guess approach, by contrast, can be dragged out by a long first word regardless of how short the real prefix is. The lesson generalizes past this one problem: when a question asks you to compare many sequences at the same positions — a shared prefix, a first point of divergence, a per-column vote — think about reading down the columns and stopping at the first disagreement, rather than processing each sequence whole. And carry the two guard rails from the Crucial Note onto any column scan: a sequence can end early, and the order in which you test "ended" versus "differs" decides whether the code is correct or crashes.
Vertical Scanning
Column 0: reference character is 'F' from "FLOWER".