LeetCode 2288, Apply Discount to Prices, is a deceptively simple string-processing problem. At first glance, it looks like a basic split-and-replace task, but the challenge lies in carefully identifying what counts as a valid price and formatting the discounted value correctly. This problem is a great exercise in parsing, validation, and precision formatting.
TLDR: Split the sentence into words, check each word to see whether it is a valid price, and apply the discount only to valid prices. A valid price must start with $ and be followed by one or more digits only. Convert the numeric part to an integer, apply the discount, format it with exactly two decimal places, and join the words back together.
Understanding the Problem
You are given a string sentence and an integer discount. The sentence contains words separated by single spaces. Some of these words may represent prices, and prices follow a very specific format:
- The word must start with the dollar sign
$. - After the dollar sign, there must be at least one digit.
- All characters after
$must be digits from0to9.
If a word is a valid price, we apply the discount and replace it with the new price formatted to exactly two decimal places. If a word is not a valid price, it stays unchanged.
For example, consider:
sentence = "there are $1 $2 and 5$ candies in the shop"
discount = 50
The valid prices are $1 and $2. The word 5$ is not valid because it does not start with $. After applying a 50% discount, the sentence becomes:
"there are $0.50 $1.00 and 5$ candies in the shop"
Key Observation
The important part of this problem is not the discount calculation itself. The real trick is determining whether a word is a valid price. Many strings may look price-like, but they should not be discounted.
Let’s look at some examples:
$100is valid.$0is valid.$001is valid because the part after$contains only digits.$is not valid because there are no digits after the dollar sign.$12ais not valid because it contains a letter.12$is not valid because it does not start with$.$$5is not valid because after the first$, the rest is not all digits.
Once we understand this distinction, the solution becomes straightforward.
Approach
The cleanest approach is to process the sentence word by word. Because the problem states that words are separated by spaces, we can use split() to get all words, transform valid price words, and then use join() to rebuild the sentence.
For each word:
- Check if it starts with
$. - Check if it has at least two characters, since
$alone is not a price. - Check if every character after
$is a digit. - If valid, convert the numeric part to an integer.
- Apply the discount formula.
- Format the result with exactly two decimal places.
The discount formula is:
discounted_price = original_price * (100 - discount) / 100
For example, if the original price is 200 and the discount is 25, then:
200 * (100 - 25) / 100 = 150.00
The final displayed price should be $150.00.
Python Solution
class Solution:
def discountPrices(self, sentence: str, discount: int) -> str:
words = sentence.split()
result = []
for word in words:
if len(word) >= 2 and word[0] == '$' and word[1:].isdigit():
price = int(word[1:])
discounted_price = price * (100 - discount) / 100
result.append(f"${discounted_price:.2f}")
else:
result.append(word)
return " ".join(result)
Code Explanation
Let’s walk through the solution line by line.
words = sentence.split()
This breaks the sentence into a list of words. Since the input uses spaces between words, this is exactly what we need.
result = []
We create an empty list to store the transformed words. Building a list and joining it later is more efficient and cleaner than repeatedly concatenating strings.
if len(word) >= 2 and word[0] == '$' and word[1:].isdigit():
This condition checks whether the current word is a valid price. It requires three things:
len(word) >= 2: the word must contain a dollar sign and at least one digit.word[0] == '$': the word must begin with a dollar sign.word[1:].isdigit(): everything after the dollar sign must be numeric.
If all three conditions are true, the word is a valid price.
price = int(word[1:])
Here we remove the dollar sign and convert the remaining digits into an integer. This also handles values with leading zeros, such as $0012, which becomes 12.
discounted_price = price * (100 - discount) / 100
This calculates the new price after applying the discount.
result.append(f"${discounted_price:.2f}")
This is the formatting step. The expression :.2f ensures the number always has exactly two digits after the decimal point. So 5 becomes 5.00, and 2.5 becomes 2.50.
If the word is not a valid price, we simply add it unchanged:
result.append(word)
Finally:
return " ".join(result)
This combines all processed words back into a sentence.
Example Walkthrough
Consider this input:
sentence = "1 2 $3 4 $5 $abc $10"
discount = 20
The words are:
1: not a price2: not a price$3: valid, becomes$2.404: not a price$5: valid, becomes$4.00$abc: invalid, contains letters$10: valid, becomes$8.00
The final output is:
"1 2 $2.40 4 $4.00 $abc $8.00"
Complexity Analysis
Let n be the length of the sentence.
- Time Complexity:
O(n). Each character is inspected a constant number of times while splitting, validating, and joining. - Space Complexity:
O(n). We store the split words and the final transformed result.
Common Pitfalls
Forgetting that $ alone is invalid: A word must have at least one digit after the dollar sign.
Discounting invalid strings: Words like $5a, 5$, and $$5 should remain unchanged.
Incorrect decimal formatting: The output must always show exactly two decimal places, even when the result is a whole number.
Using floating-point formatting incorrectly: The calculation may produce a float, but formatted output with :.2f is enough for this problem.
Final Thoughts
LeetCode 2288 is an excellent reminder that string problems often depend on precise definitions. The discount formula is simple, but the validation rules must be followed carefully. By splitting the sentence into words, checking each word with clear conditions, and formatting valid prices properly, we get a concise and efficient solution.
The main takeaway is this: validate first, transform second. Once the price detection logic is correct, the rest of the problem becomes easy to implement and reason about.
