Thousand Separator
EasyPrompt
Given an integer n, add a dot (".") as the thousands separator and return it in string format.
Example 1:
Input: n = 987
Output: "987"Example 2:
Input: n = 1234
Output: "1.234"
Constraints:
0 <= n <= 231 - 1
Approaches
2 approaches with complexity analysis and trade-offs.
This is a very intuitive approach. We first convert the number to a string. Then, we iterate through this string from right to left, building a new string. We keep a counter to track digits, and every three digits, we add a dot. Since we build the result string in reverse order (from the least significant digit to the most significant), we need to reverse it at the end to get the final correct format.
Algorithm
- Convert the input integer
nto its string representation, let's call its. - If the length of
sis less than or equal to 3, no separator is needed. Returnsdirectly. - Initialize a
StringBuilderto construct the result. - Initialize a counter,
digitCount, to 0. - Loop through the string
sfrom the last character to the first (indexs.length() - 1down to0). - Inside the loop, append the current character to the
StringBuilder. - Increment
digitCount. - Check if
digitCountis 3 and if we are not at the very beginning of the string (i.e., the loop index is not 0). If both conditions are true, append a.separator to theStringBuilderand resetdigitCountto 0. - After the loop completes, the
StringBuilderholds the formatted string but in reverse order. - Call the
reverse()method on theStringBuilderand then convert it to a string to get the final answer.
Walkthrough
This approach works by processing the number's string representation from right to left, which is the natural way to group digits into thousands. A StringBuilder is used for efficient string construction.
class Solution { public String thousandSeparator(int n) { String s = Integer.toString(n); if (s.length() <= 3) { return s; } StringBuilder resultBuilder = new StringBuilder(); int count = 0; for (int i = s.length() - 1; i >= 0; i--) { resultBuilder.append(s.charAt(i)); count++; // Add a dot after every 3 digits, but not at the very beginning if (count % 3 == 0 && i > 0) { resultBuilder.append('.'); } } // The string was built backwards, so we need to reverse it return resultBuilder.reverse().toString(); }}Complexity
Time
O(L), where L is the number of digits in `n`. Converting the integer to a string takes O(L). The loop iterates L times, and operations inside (appending to `StringBuilder`) are amortized O(1). The final reversal also takes O(L).
Space
O(L), where L is the number of digits in `n`. The `StringBuilder` requires space proportional to the number of digits plus the separators.
Trade-offs
Pros
The logic is simple and follows a natural way of thinking about the problem (grouping from the right).
Easy to implement correctly.
Cons
Requires a final reversal step, which adds an extra pass over the constructed string.
This approach is a slight optimization over the previous one. It avoids the final reversal by first calculating the length of the initial group of digits (the ones before the first separator) and then appending the remaining groups of three, each preceded by a dot. This builds the string in the correct order from left to right.
Algorithm
- Convert the integer
nto its string representation,s. - Get the length of the string,
len. Iflen <= 3, returns. - Calculate the length of the first group of digits. This is
len % 3. Iflenis a multiple of 3, the first group has 3 digits; otherwise, it haslen % 3digits. Let's call thisfirstGroupLen. - Initialize a
StringBuilder. - Append the first group of digits (from index 0 to
firstGroupLen) fromsto theStringBuilder. - Loop from
firstGroupLento the end of the strings, incrementing the index by 3 in each step. - In each iteration, append a
.separator to theStringBuilder. - Then, append the next group of 3 digits from
s. - After the loop, convert the
StringBuilderto a string and return it.
Walkthrough
By pre-calculating the length of the first segment of numbers, we can construct the formatted string from left to right, eliminating the need for a final reversal step. This makes the process more direct.
class Solution { public String thousandSeparator(int n) { String s = Integer.toString(n); int len = s.length(); if (len <= 3) { return s; } StringBuilder sb = new StringBuilder(); int firstGroupLen = len % 3; if (firstGroupLen == 0) { // If length is a multiple of 3, the first group has 3 digits firstGroupLen = 3; } // Append the first group sb.append(s.substring(0, firstGroupLen)); // Append the remaining groups for (int i = firstGroupLen; i < len; i += 3) { sb.append('.'); sb.append(s.substring(i, i + 3)); } return sb.toString(); }}Complexity
Time
O(L), where L is the number of digits. String conversion is O(L). The loop runs approximately L/3 times. Inside the loop, `substring` and `append` operations contribute to an overall linear time complexity.
Space
O(L), where L is the number of digits. The `StringBuilder` stores the result, which has a length proportional to L.
Trade-offs
Pros
Builds the string in the correct order, avoiding the need for a final reversal.
Potentially slightly more performant than the reversal approach due to fewer overall operations.
Cons
The logic for determining the length of the first group adds a small amount of complexity compared to the straightforward right-to-left iteration.
Solutions
Solution
class Solution {public String thousandSeparator(int n) { int cnt = 0; StringBuilder ans = new StringBuilder(); while (true) { int v = n % 10; n /= 10; ans.append(v); ++cnt; if (n == 0) { break; } if (cnt == 3) { ans.append('.'); cnt = 0; } } return ans.reverse().toString(); }}class Solution {public: string thousandSeparator(int n) { int cnt = 0; string ans; while (1) { int v = n % 10; n /= 10; ans += to_string(v); if (n == 0) break; if (++cnt == 3) { ans += '.'; cnt = 0; } } reverse(ans.begin(), ans.end()); return ans; }};class Solution: def thousandSeparator(self, n: int) -> str: cnt = 0 ans = [] while 1: n, v = divmod(n, 10) ans . append(str(v)) cnt += 1 if n == 0: break if cnt == 3: ans . append('.') cnt = 0 return '' . join(ans[:: - 1])Video walkthrough
Newsletter
One sharp idea, every week
System design and interview prep — short enough to finish.
No spam. Unsubscribe anytime.
Practice
Same difficulty — related problems to reinforce the pattern.