LeetCode 2118 - Build the Equation
The problem asks us to construct a polynomial equation from a database table called Terms. Each row in the table represents a single term in the equation, where power is the exponent of X and factor is the coefficient.
Difficulty: 🔴 Hard
Topics: Database
Solution
Problem Understanding
The problem asks us to construct a polynomial equation from a database table called Terms. Each row in the table represents a single term in the equation, where power is the exponent of X and factor is the coefficient. The goal is to output a single string representing the equation, where all terms are concatenated in descending order of their powers, and the right-hand side is always zero.
The output format is very strict: each term must start with a sign (+ or -), followed by the absolute value of the factor, then X raised to the power if the power is greater than 1. If the power is 1, only X appears without the exponent. If the power is 0, only the number appears without X. This requires careful handling of string formatting and ordering.
The input guarantees that factor is non-zero and power is unique, which simplifies the problem. Important edge cases include negative coefficients, powers of 0 or 1, and a table with only one term.
The follow-up, where power may not be unique, would require first summing the coefficients for the same power before constructing the equation string.
Approaches
The brute-force approach is straightforward: read all terms from the table, sort them by descending power, and manually build the string by iterating over each row. Each term requires conditional formatting based on its power. This works because the dataset is small (power ≤ 100), but it does not scale well if additional operations like summing duplicate powers are needed. The brute-force approach is correct but mechanically repetitive.
The optimal approach leverages SQL's string functions along with an ORDER BY clause to sort powers in descending order. For each term, we conditionally format the string depending on the power using CASE statements. This avoids post-processing in application code and ensures the string is built directly in the database query. It is more elegant and scales better with the number of terms.
| Approach | Time Complexity | Space Complexity | Notes |
|---|---|---|---|
| Brute Force | O(n log n) | O(n) | Sort in application and format each term manually |
| Optimal | O(n log n) | O(1) | Sort in SQL and build string using aggregation and CASE |
Algorithm Walkthrough
- Start by reading all rows from the
Termstable. - Sort the rows in descending order of
power. - For each term, determine the string representation based on
power:
- If
power = 0, append+factoror-factor. - If
power = 1, append+factorXor-factorX. - Otherwise, append
+factorX^poweror-factorX^power.
- Use the absolute value of the factor when writing the term, but prepend the sign based on the original factor.
- Concatenate all formatted terms into a single string.
- Append
=0at the end to complete the equation. - Return the resulting string as a single column named
equation.
Why it works: By sorting powers in descending order and formatting each term correctly, we maintain the correct order and mathematical representation of the polynomial. Using the absolute value of the factor with the sign ensures that both positive and negative terms are represented correctly.
Python Solution
import sqlite3
from typing import List, Tuple
def buildEquation(terms: List[Tuple[int, int]]) -> str:
# Sort terms in descending order of power
terms.sort(key=lambda x: -x[0])
equation_parts = []
for power, factor in terms:
sign = '+' if factor > 0 else '-'
abs_factor = abs(factor)
if power == 0:
term_str = f"{sign}{abs_factor}"
elif power == 1:
term_str = f"{sign}{abs_factor}X"
else:
term_str = f"{sign}{abs_factor}X^{power}"
equation_parts.append(term_str)
return ''.join(equation_parts) + '=0'
The code first sorts the list of tuples in descending order of powers. Then, for each term, it constructs the string based on the power. The sign is determined from the factor, and the absolute value is used in the string. Finally, all strings are concatenated and =0 is appended to form the complete equation.
Go Solution
package main
import (
"fmt"
"sort"
"strconv"
)
type Term struct {
Power int
Factor int
}
func buildEquation(terms []Term) string {
sort.Slice(terms, func(i, j int) bool {
return terms[i].Power > terms[j].Power
})
equation := ""
for _, term := range terms {
sign := "+"
if term.Factor < 0 {
sign = "-"
}
absFactor := term.Factor
if absFactor < 0 {
absFactor = -absFactor
}
var part string
if term.Power == 0 {
part = fmt.Sprintf("%s%d", sign, absFactor)
} else if term.Power == 1 {
part = fmt.Sprintf("%s%dX", sign, absFactor)
} else {
part = fmt.Sprintf("%s%dX^%d", sign, absFactor, term.Power)
}
equation += part
}
equation += "=0"
return equation
}
The Go implementation mirrors Python. We sort the slice of terms by descending power, determine the sign and absolute value, then construct the formatted string using fmt.Sprintf. Finally, we concatenate all parts and append =0.
Worked Examples
Example 1:
Input: [(2, 1), (1, -4), (0, 2)]
Sorted by power: [(2,1),(1,-4),(0,2)]
| Power | Factor | Sign | Term String |
|---|---|---|---|
| 2 | 1 | + | +1X^2 |
| 1 | -4 | - | -4X |
| 0 | 2 | + | +2 |
Concatenated string: +1X^2-4X+2=0
Example 2:
Input: [(4, -4), (2, 1), (1, -1)]
Sorted by power: [(4,-4),(2,1),(1,-1)]
| Power | Factor | Sign | Term String |
|---|---|---|---|
| 4 | -4 | - | -4X^4 |
| 2 | 1 | + | +1X^2 |
| 1 | -1 | - | -1X |
Concatenated string: -4X^4+1X^2-1X=0
Complexity Analysis
| Measure | Complexity | Explanation |
|---|---|---|
| Time | O(n log n) | Sorting terms by power dominates the complexity |
| Space | O(n) | Storing formatted strings in a list before joining |
The sorting step requires O(n log n), while building the string requires a single pass over the list O(n).
Test Cases
# Provided examples
assert buildEquation([(2,1),(1,-4),(0,2)]) == "+1X^2-4X+2=0"
assert buildEquation([(4,-4),(2,1),(1,-1)]) == "-4X^4+1X^2-1X=0"
# Single term
assert buildEquation([(0,5)]) == "+5=0"
assert buildEquation([(1,-3)]) == "-3X=0"
# Negative factors
assert buildEquation([(3,-2),(0,-1)]) == "-2X^3-1=0"
# Mixed powers and factors
assert buildEquation([(2,3),(1,4),(0,-5)]) == "+3X^2+4X-5=0"
# Powers not in order
assert buildEquation([(0,1),(3,-2),(1,3)]) == "-2X^3+3X+1=0"
| Test | Why |
|---|---|
| Provided examples | Validates standard case handling |
| Single term | Ensures formatting works with only one term |
| Negative factors | Checks correct handling of negative numbers |
| Mixed powers and factors | Validates correct concatenation order and signs |
| Powers not in order | Ensures sorting is applied before formatting |
Edge Cases
One edge case is when the polynomial has only one term. The algorithm correctly adds the sign and =0 regardless of the term's power. Another edge case is when the power is 0 or 1, which requires conditional formatting to avoid adding X or ^1 incorrectly. A third edge case is negative coefficients, which must prepend - and use the absolute value in the term string. The algorithm handles this consistently by checking the sign and using abs() or equivalent logic.