Skip to content
← All posts

Compare Version Numbers: Split and Compare Revisions

4 min read
leetcodeproblemmediumstrings

Compare Version Numbers is LeetCode 165. You are given two version strings version1 and version2. Each version string consists of revisions separated by dots. Compare them revision by revision from left to right. If one version string has fewer revisions than the other, treat the missing revisions as 0. Return -1 if version1 is smaller, 1 if it is larger, or 0 if they are equal.

Examples:

  • version1 = "1.2", version2 = "1.10" returns -1 because revision 1 gives 2 vs 10, and 2 is less than 10.
  • version1 = "1.01", version2 = "1.001" returns 0 because leading zeros do not matter: int("01") and int("001") are both 1.
  • version1 = "1.0", version2 = "1.0.0" returns 0 because the missing third revision of version1 is treated as 0, matching version2.
rev 0rev 1"1.2"12"1.10"1101 == 12 < 10
Revisions aligned side by side. Rev 0 matches (both 1). Rev 1 differs: 2 vs 10. Since 2 is less than 10, return -1.

The approach

The core idea is to split each version string by ".", convert each revision to an integer, and compare them one at a time.

Here is the process:

  1. Split both version strings on "." to get arrays of revision strings
  2. Walk through both arrays simultaneously, index by index
  3. At each index, convert both revisions to integers. If one array is shorter, use 0 for the missing revision
  4. If the two integers differ, return -1 or 1 depending on which is smaller
  5. If you finish all revisions without finding a difference, return 0

Converting to integers handles leading zeros automatically. int("001") is just 1, so "1.001" and "1.1" are treated as equal. The zero-padding for missing revisions handles different lengths, so "1.0" and "1.0.0" compare as equal too.

You do not need to explicitly pad the shorter array with zeros. Instead, when an index is past the end of one array, just use 0 as the value. This avoids creating any extra data and keeps the code clean.

The solution

def compareVersion(version1: str, version2: str) -> int:
    v1 = version1.split(".")
    v2 = version2.split(".")
    for i in range(max(len(v1), len(v2))):
        n1 = int(v1[i]) if i < len(v1) else 0
        n2 = int(v2[i]) if i < len(v2) else 0
        if n1 < n2:
            return -1
        if n1 > n2:
            return 1
    return 0

Walkthrough

Let's trace through version1 = "1.0" and version2 = "1.0.0". This is the trickiest example because the versions have different numbers of revisions but are still equal.

Step 1: Split by "."

v110v2100

version1 "1.0" splits into ["1", "0"]. version2 "1.0.0" splits into ["1", "0", "0"]. version2 has one more revision.

Step 2: Compare revision 0

v110v2100

int("1") == int("1"). Equal so far. Move to the next revision.

Step 3: Compare revision 1

v110v2100

int("0") == int("0"). Still equal. Move to revision 2.

Step 4: Compare revision 2 (padded)

v1100*v2100

version1 has no revision 2, so treat it as 0. int(0) == int("0"). Equal. No more revisions.

Step 5: Result

v1100*v2100

All revisions matched. Return 0 (versions are equal).

The algorithm compared all three revision positions (padding version1 with a virtual zero at index 2) and found them all equal. That trailing .0 in version2 made no difference because the padded zero matched it exactly.

Complexity analysis

Time: O(m + n) where m is the length of version1 and n is the length of version2. The split(".") call scans each string once. The comparison loop runs at most max(r1, r2) iterations where r1 and r2 are the revision counts, which is bounded by the string lengths.

Space: O(m + n) for storing the two arrays of revision strings after splitting. Each character in the original string ends up in exactly one element of the split array.

AspectValue
TimeO(m + n)
SpaceO(m + n)
DifficultyMedium

Building blocks

This problem is built from two fundamental techniques that appear across many string problems.

String splitting

The entire problem hinges on splitting a string by a delimiter. version1.split(".") turns "1.0.3" into ["1", "0", "3"]. This same operation appears in problems involving IP addresses, file paths, CSV parsing, and any structured string format. Knowing how split works, including that consecutive delimiters produce empty strings in some languages, is essential.

Padded comparison

When two sequences have different lengths, you treat the missing elements as a default value (here, 0) and continue comparing. This is the same idea used in Add Binary, Add Two Numbers, and Merge Sorted Arrays. The pattern is always the same: iterate up to the maximum length of the two sequences, and when one is exhausted, substitute the identity element.

Edge cases

Trailing zeros. "1.0" vs "1.0.0" should return 0. The extra .0 revisions contribute nothing because they are treated as 0, matching the padded zeros from the shorter version.

Leading zeros in a revision. "1.01" vs "1.001" should return 0. Converting "01" and "001" to integers both give 1. The int() call strips leading zeros automatically.

Different lengths with a real difference. "1.0.1" vs "1.0" should return 1. When you reach revision 2, version1 has 1 while version2 is padded to 0. Since 1 is greater than 0, you return 1.

Equal versions. "1.0" vs "1.0" returns 0. The loop compares each revision, finds them equal, and falls through to the final return 0.

From understanding to recall

This solution looks simple, and it is. But simplicity is deceptive when it comes to recall. Under interview pressure, the details matter: remembering to iterate up to max(len(v1), len(v2)) rather than min, using int() to handle leading zeros, defaulting to 0 when one array is shorter. Miss any one of those and the solution breaks on edge cases.

Spaced repetition locks in these details. You type the solution from scratch, verify it, and revisit it a few days later. Each repetition reinforces the specific choices that make the code correct: the max in the loop bound, the conditional int(v1[i]) if i < len(v1) else 0, and the three-way return logic. After a few reps, the pattern is automatic.

Related posts

  • Longest Common Prefix - Another string comparison problem that involves scanning multiple strings position by position
  • Add Binary - Uses the same padded comparison technique, walking two sequences of different lengths and substituting zeros for the shorter one