LeetCode 1880 - Check if Word Equals Summation of Two Words
The problem asks us to determine if the sum of the numerical values of two words equals the numerical value of a third word. Each word consists of lowercase letters from 'a' to 'j'.
Difficulty: 🟢 Easy
Topics: String
Solution
Problem Understanding
The problem asks us to determine if the sum of the numerical values of two words equals the numerical value of a third word. Each word consists of lowercase letters from 'a' to 'j'. Each letter has a letter value, which is its zero-based position in the alphabet ('a' -> 0, 'b' -> 1, …, 'j' -> 9). The numerical value of a word is obtained by concatenating the letter values of its characters as a string and then converting that string to an integer.
For example, "acb" translates to "021", which becomes integer 21. The task is to check whether:
numerical_value(firstWord) + numerical_value(secondWord) == numerical_value(targetWord)
The constraints are very manageable: each word has a length from 1 to 8, and the letters are restricted to 'a' through 'j'. This ensures that the integer formed will be at most 8 digits long and thus fits within typical integer types in both Python and Go. Important edge cases include words that translate to numbers with leading zeros, such as "aaa" becoming 0, which could cause naive implementations that convert letters individually and sum digits to fail.
Approaches
The brute-force approach involves explicitly converting each letter in a word to its letter value, building the string representation of the number, and converting it to an integer. We do this for all three words and then check the sum. This is straightforward, correct, and efficient given the small constraints, but the inefficiency comes from repeated string concatenations and conversions, which can be avoided.
The optimal approach recognizes that instead of concatenating strings, we can compute the integer value directly by iterating through each character and multiplying the current total by 10 before adding the new letter value. This eliminates string operations entirely and directly computes the integer. This approach is slightly faster and avoids unnecessary memory usage.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n) | O(n) | Build strings of letter values then convert to int |
| Optimal | O(n) | O(1) | Compute integer directly using arithmetic |
Algorithm Walkthrough
- Define a helper function
wordToNumber(word)that converts a word to its numerical value. Initializenum = 0. - Iterate through each character
cin the word. Compute the letter value asord(c) - ord('a'). - Multiply
numby 10 and add the letter value. This builds the integer without string concatenation. - Return
num. - Apply this helper to
firstWord,secondWord, andtargetWordto getnum1,num2, andnumTarget. - Return
Trueifnum1 + num2 == numTarget, else returnFalse.
Why it works: Each step of multiplying by 10 and adding the letter value correctly simulates the concatenation of digits. Since the input length is limited and only letters 'a' to 'j' are used, integer overflow is not a concern, and the final sum comparison is accurate.
The problem defines a custom way to convert a word into a number. Each lowercase character from 'a' to 'j' maps to a digit from 0 to 9 based on its alphabetical position. For example, 'a' becomes 0, 'b' becomes 1, and 'j' becomes 9.
To compute the numerical value of a word, we replace every character with its digit and concatenate the results into a string. That resulting string is then interpreted as an integer. For example, the word "acb" becomes "021", which converts to the integer 21 because leading zeros are ignored during integer conversion.
The task is to determine whether:
numerical_value(firstWord) + numerical_value(secondWord)
==
numerical_value(targetWord)
The input consists of three strings:
firstWordsecondWordtargetWord
All characters are guaranteed to be between 'a' and 'j', which means every character maps cleanly to a single decimal digit.
The expected output is a boolean value:
trueif the sum of the first two numerical values equals the thirdfalseotherwise
The constraints are very small. Each string has length at most 8, so the largest possible generated number has at most 8 digits. This means integer overflow is not a concern in Python, and it is also safe in Go because an 8 digit integer easily fits inside a standard int.
There are several edge cases worth considering. Leading zeros are the most important one. A word like "aaa" becomes "000", which converts to integer 0. A naive implementation that compares strings instead of integers would fail in these situations. Another important case is when all words evaluate to zero. The problem guarantees valid lowercase characters from 'a' to 'j', so we never need to handle invalid input or multi digit character mappings.
Approaches
Brute Force Approach
A brute force approach would explicitly build the digit string for every word character by character, store the entire converted string, then parse the string into an integer. After converting all three words, we compare whether the sum of the first two integers equals the third.
This approach is correct because it follows the problem definition exactly. Every character is translated into its corresponding digit, the digits are concatenated in order, and the resulting string is converted into an integer.
Although this solution is already efficient enough for the given constraints, it performs unnecessary intermediate string operations. We allocate extra memory for temporary strings and repeatedly concatenate characters.
Optimal Approach
The key observation is that the conversion process is essentially constructing a base-10 integer digit by digit. Instead of building a string first and converting later, we can directly compute the integer value while iterating through the word.
For each character:
current_value = current_value * 10 + digit
This mirrors how decimal numbers are formed mathematically.
For example:
"acb"
'a' -> 0
value = 0 * 10 + 0 = 0
'c' -> 2
value = 0 * 10 + 2 = 2
'b' -> 1
value = 2 * 10 + 1 = 21
This avoids temporary strings entirely and produces the same result more efficiently and cleanly.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n) | O(n) | Builds intermediate strings before integer conversion |
| Optimal | O(n) | O(1) | Computes integer values directly during traversal |
Here, n represents the total number of characters across all three words.
Algorithm Walkthrough
- Create a helper function that converts a word into its numerical value. This helper keeps the logic reusable and avoids duplicate code.
- Initialize an integer variable called
valueto0. This variable will store the progressively constructed number. - Traverse each character in the word from left to right. The order matters because the problem defines the number using concatenation.
- Convert the current character into its digit value using:
ord(character) - ord('a')
This works because the letters are consecutive in ASCII order. For example:
ord('c') - ord('a') = 2
- Update the current number using:
value = value * 10 + digit
Multiplying by 10 shifts all existing digits one place to the left, and adding the new digit appends it to the number.
6. After processing all characters, return the computed integer value.
7. Compute the numerical values of firstWord, secondWord, and targetWord.
8. Return whether:
first_value + second_value == target_value
Why it works
The algorithm maintains the invariant that after processing the first k characters of a word, value equals the integer formed by concatenating the mapped digits of those k characters. Each step multiplies the current number by 10 and appends the next digit, exactly matching decimal number construction. Since every character is processed in order and converted correctly, the final computed integer matches the numerical value defined in the problem statement.
Python Solution
class Solution:
def isSumEqual(self, firstWord: str, secondWord: str, targetWord: str) -> bool:
def wordToNumber(word: str) -> int:
num = 0
for c in word:
num = num * 10 + (ord(c) - ord('a'))
return num
num1 = wordToNumber(firstWord)
num2 = wordToNumber(secondWord)
numTarget = wordToNumber(targetWord)
return num1 + num2 == numTarget
The Python solution uses a helper function wordToNumber to transform words into integers efficiently. The main method then simply compares the sum of the first two numbers with the target number. Multiplying num by 10 at each step simulates concatenating the digits of the letter values without creating intermediate strings.
def word_to_number(word: str) -> int:
value = 0
for character in word:
digit = ord(character) - ord('a')
value = value * 10 + digit
return value
first_value = word_to_number(firstWord)
second_value = word_to_number(secondWord)
target_value = word_to_number(targetWord)
return first_value + second_value == target_value
The implementation starts by defining a helper function named `word_to_number`. This function converts a word into its corresponding integer value using direct mathematical construction instead of string concatenation.
Inside the helper, `value` starts at `0`. For each character, we compute its digit value by subtracting the ASCII value of `'a'`. The expression:
```python
ord(character) - ord('a')
maps 'a' to 0, 'b' to 1, and so on.
The line:
value = value * 10 + digit
appends the digit to the current number exactly as decimal numbers are formed.
After converting all three words, the solution compares whether the sum of the first two numerical values equals the target numerical value.
The implementation is concise, avoids unnecessary memory allocation, and directly models the mathematical definition from the problem statement.
Go Solution
func isSumEqual(firstWord string, secondWord string, targetWord string) bool {
wordToNumber := func(word string) int {
num := 0
for _, c := range word {
num = num*10 + int(c-'a')
}
return num
}
num1 := wordToNumber(firstWord)
num2 := wordToNumber(secondWord)
numTarget := wordToNumber(targetWord)
return num1 + num2 == numTarget
}
In Go, the solution uses an anonymous function wordToNumber that iterates over runes of the string. The arithmetic logic mirrors Python. Since Go uses fixed-size integers, the constraints guarantee no overflow.
Worked Examples
Example 1: firstWord = "acb", secondWord = "cba", targetWord = "cdb"
| Step | Variable | Value |
|---|---|---|
| Convert firstWord | num1 | 0_10+0=0 → 0_10+2=2 → 2*10+1=21 |
| Convert secondWord | num2 | 2_10+2=2 → 2_10+1=21? Correction: 2_10+1=21 → 21_10+0=210 |
| Convert targetWord | numTarget | 2_10+3=23 → 23_10+1=231 |
| Sum comparison | 21+210==231 | True |
Example 2: firstWord = "aaa", secondWord = "a", targetWord = "aab"
| Step | Variable | Value |
|---|---|---|
| Convert firstWord | num1 | 0_10+0=0 → 0_10+0=0 → 0*10+0=0 |
| Convert secondWord | num2 | 0 |
| Convert targetWord | numTarget | 0_10+0=0 → 0_10+0=0 → 0*10+1=1 |
| Sum comparison | 0+0==1 | False |
Example 3: firstWord = "aaa", secondWord = "a", targetWord = "aaaa"
| Step | Variable | Value |
|---|---|---|
| Convert firstWord | num1 | 0 |
| Convert secondWord | num2 | 0 |
| Convert targetWord | numTarget | 0 |
| Sum comparison | 0+0==0 | True |
wordToNumber := func(word string) int {
value := 0
for _, character := range word {
digit := int(character - 'a')
value = value*10 + digit
}
return value
}
firstValue := wordToNumber(firstWord)
secondValue := wordToNumber(secondWord)
targetValue := wordToNumber(targetWord)
return firstValue+secondValue == targetValue
}
The Go implementation follows the same logic as the Python version. A local helper function converts each word into its numerical value using arithmetic construction.
One Go-specific detail is the use of rune iteration in the `for _, character := range word` loop. Since the input contains only lowercase English letters, rune handling is straightforward and safe.
Integer overflow is not a concern because the maximum generated number contains only eight digits, which easily fits within Go's standard `int` type.
Unlike Python, Go requires explicit type conversion when computing the digit value:
```go
digit := int(character - 'a')
Otherwise, the algorithm remains identical.
Worked Examples
Example 1
Input:
firstWord = "acb"
secondWord = "cba"
targetWord = "cdb"
Converting "acb"
| Character | Digit | Current Value |
|---|---|---|
| a | 0 | 0 |
| c | 2 | 2 |
| b | 1 | 21 |
Final value: 21
Converting "cba"
| Character | Digit | Current Value |
|---|---|---|
| c | 2 | 2 |
| b | 1 | 21 |
| a | 0 | 210 |
Final value: 210
Converting "cdb"
| Character | Digit | Current Value |
|---|---|---|
| c | 2 | 2 |
| d | 3 | 23 |
| b | 1 | 231 |
Final value: 231
Final comparison:
21 + 210 = 231
Result:
true
Example 2
Input:
firstWord = "aaa"
secondWord = "a"
targetWord = "aab"
Converting "aaa"
| Character | Digit | Current Value |
|---|---|---|
| a | 0 | 0 |
| a | 0 | 0 |
| a | 0 | 0 |
Final value: 0
Converting "a"
| Character | Digit | Current Value |
|---|---|---|
| a | 0 | 0 |
Final value: 0
Converting "aab"
| Character | Digit | Current Value |
|---|---|---|
| a | 0 | 0 |
| a | 0 | 0 |
| b | 1 | 1 |
Final value: 1
Final comparison:
0 + 0 = 0
Since:
0 != 1
Result:
false
Example 3
Input:
firstWord = "aaa"
secondWord = "a"
targetWord = "aaaa"
Converting "aaa"
| Character | Digit | Current Value |
|---|---|---|
| a | 0 | 0 |
| a | 0 | 0 |
| a | 0 | 0 |
Final value: 0
Converting "a"
| Character | Digit | Current Value |
|---|---|---|
| a | 0 | 0 |
Final value: 0
Converting "aaaa"
| Character | Digit | Current Value |
|---|---|---|
| a | 0 | 0 |
| a | 0 | 0 |
| a | 0 | 0 |
| a | 0 | 0 |
Final value: 0
Final comparison:
0 + 0 = 0
Result:
true
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n) | Each word is processed once, iterating over its characters |
| Space | O(1) | Only a few integer variables are used; no extra data structures |
The reasoning is straightforward: each word length is small (≤8), so even the naive approach is fast, and the arithmetic method avoids extra space for string concatenations. | Time | O(n) | Each character across all words is processed exactly once | | Space | O(1) | Only a few integer variables are used |
The algorithm performs a single pass over each input string. Since each character is visited exactly once, the runtime grows linearly with the total number of characters. No auxiliary data structures proportional to input size are created, so the extra space usage remains constant.
Test Cases
# Provided examples
assert Solution().isSumEqual("acb", "cba", "cdb") == True # standard case
assert Solution().isSumEqual("aaa", "a", "aab") == False # leading zeros
assert Solution().isSumEqual("aaa", "a", "aaaa") == True # sum zero
# Edge / boundary cases
assert Solution().isSumEqual("a", "a", "b") == True # smallest words
assert Solution().isSumEqual("j", "j", "ii") == True # highest letters
assert Solution().isSumEqual("abcdefgh", "a", "abcdefgh") == False # long words
assert Solution().isSumEqual("a", "a", "aa") == False # leading zero sum mismatch
solution = Solution()
assert solution.isSumEqual("acb", "cba", "cdb") == True # provided example, normal case
assert solution.isSumEqual("aaa", "a", "aab") == False # provided example, leading zeros
assert solution.isSumEqual("aaa", "a", "aaaa") == True # provided example, all zeros
assert solution.isSumEqual("a", "a", "a") == True # 0 + 0 = 0
assert solution.isSumEqual("b", "c", "d") == False # 1 + 2 != 3
assert solution.isSumEqual("b", "c", "de") == True # 1 + 2 = 3
assert solution.isSumEqual("j", "j", "bi") == False # 9 + 9 = 18, "bi" = 18? actually 18, wait check
assert solution.isSumEqual("j", "j", "bi") == True # correct arithmetic validation
assert solution.isSumEqual("abcdefgh", "a", "abcdefgh") == True # adding zero changes nothing
assert solution.isSumEqual("jjjjjjjj", "a", "jjjjjjjj") == True # maximum length input
assert solution.isSumEqual("abc", "def", "ghij") == False # clearly unequal values
assert solution.isSumEqual("c", "d", "f") == False # 2 + 3 != 5 because "f" = 5, actually true
assert solution.isSumEqual("c", "d", "f") == True # corrected arithmetic check
| Test | Why |
|---|---|
"acb", "cba", "cdb" |
Validates normal concatenation sum |
"aaa", "a", "aab" |
Checks handling of leading zeros |
"aaa", "a", "aaaa" |
Verifies zero sum case |
"a", "a", "b" |
Minimal length inputs |
"j", "j", "ii" |
Max letter values, small sum |
"abcdefgh", "a", "abcdefgh" |
Maximum length input |
"a", "a", "aa" |
Leading zero mismatch |
Edge Cases
Leading Zeros: Words like "aaa" become 0. A naive implementation that sums letter values instead of concatenating digits would fail. Using multiplication by 10 ensures proper construction of the integer.
Maximum Letter Value: The letter 'j' corresponds to 9. Adding two maximum 8-digit numbers could theoretically overflow, but constraints guarantee integers stay within limits. In Go, int type is sufficient for 8-digit numbers.
Single Character Words: When words have length 1, the algorithm still works because the loop runs exactly once, correctly mapping the letter to its numerical value.
This thorough implementation ensures correctness, handles all edge cases, and is efficient for the problem constraints.
| "acb", "cba", "cdb" | Validates the main example from the problem |
| "aaa", "a", "aab" | Verifies handling of leading zeros |
| "aaa", "a", "aaaa" | Ensures multiple zero representations work |
| "a", "a", "a" | Smallest possible values |
| "b", "c", "d" | Simple inequality case |
| "b", "c", "de" | Simple equality case |
| "j", "j", "bi" | Tests multi digit arithmetic |
| "abcdefgh", "a", "abcdefgh" | Adding zero should preserve value |
| "jjjjjjjj", "a", "jjjjjjjj" | Maximum length boundary |
| "abc", "def", "ghij" | Larger unequal values |
| "c", "d", "f" | Single digit equality validation |
Edge Cases
One important edge case involves leading zeros. A word like "aaa" becomes "000", which converts to integer 0. An incorrect implementation might compare strings directly and conclude that "000" differs from "0". Our implementation avoids this issue because it constructs integers mathematically, so all leading zeros naturally collapse into the correct numeric value.
Another edge case occurs when every word evaluates to zero. For example:
firstWord = "aaa"
secondWord = "aa"
targetWord = "aaaa"
All three words convert to 0. Some implementations may incorrectly assume different string lengths imply different values. Since we use integer arithmetic, the comparison works correctly regardless of how many leading zeros appear.
A third important edge case involves maximum length inputs. Each word can contain up to 8 characters, which means the generated number can contain up to 8 digits. The implementation safely handles these values because both Python integers and Go int values can easily store numbers of this size without overflow.
Another subtle case is words beginning with 'a' followed by nonzero digits, such as "abj". This becomes "019" and converts to integer 19. The arithmetic construction correctly handles this because multiplying by 10 and adding digits naturally ignores unnecessary leading zeros while preserving digit order.