1556. Thousand Separator
Problem Description
The given problem requires us to take an integer n
and format it as a string that represents the number with a dot .
inserted every three digits from the right. This is commonly known as adding a "thousand separator." For example, if n
is 123456789
, the output should be "123.456.789"
. If n
is less than 1000, it should be returned without change, since there are no thousands to separate.
Intuition
To solve this problem, one intuitive approach is to process the integer digit by digit from right to left (least significant digit to most significant digit). We can achieve that by continuously dividing the number by 10 and getting the remainder, which represents the current rightmost digit.
Each time we extract a digit, we append it to a result list. We also need to keep a count of how many digits we've added so that we know when to insert a dot. For this problem, we insert a dot every three digits. When there are no more digits left (i.e., the remaining number is 0), we stop the process. Finally, we reverse the result list since we built the number from right to left, join the elements to form a string, and return the formatted number.
Here are the specific steps of the process:
- Initialize a count
cnt
to 0. This will keep track of the number of digits processed. - Initialize an empty list
ans
to build the answer from individual digits and dots. - Enter a loop that will run until there are no more digits to process in the number
n
. Within the loop:- Divide
n
by 10, separate the quotient and the remainder. The remainder is the current digit to add to the answer, while the quotient is the reduced number for the next iteration. - Convert the remainder to a string and append it to
ans
. - Increment the count
cnt
. - If
cnt
is equal to 3 and there are still digits inn
(i.e.,n
is not 0), append a.
toans
and resetcnt
to 0.
- Divide
- Break the loop when
n
is reduced to 0. - Reverse the list
ans
since we built it backwards. - Join the elements in
ans
to form the final string. - Return the resulting string.
This method ensures that we are adding a dot every three digits while taking the basic rules of string formatting into account.
Solution Approach
The solution to this problem involves a straightforward implementation of the intuition described. The solution uses simple arithmetic operations and a list as the primary data structure to build the answer. No particular algorithmic pattern is necessary other than following this numeric processing method:
-
The solution class
Solution
contains the methodthousandSeparator
, which takes an integern
as an argument and returns a string with the formatted number. -
A counter
cnt
is initialized to 0. This counter is used to track the number of digits added to the answer listans
since the last dot was added (or since the beginning if no dot has been added yet). -
An empty list
ans
is created to accumulate the digits and dots in reverse order, as we will be processing the digits from least significant to most significant. -
The while loop
while 1:
ensures that the loop continues until explicitly broken. -
Inside the loop,
n, v = divmod(n, 10)
dividesn
by 10, storing the quotient back inn
for the next iteration and the remainder inv
. The remainder represents the current least significant digit to be added to theans
list. -
ans.append(str(v))
adds the current digit to the answer list as a string, since we want the final output to be a string. -
The counter
cnt
is incremented by 1 each time a digit is added toans
. -
A conditional
if n == 0:
checks whether the numbern
has been fully processed. Ifn
is 0, the loop is terminated by executing abreak
. -
Another conditional
if cnt == 3:
checks if three digits have been added toans
since the last dot or since the start. If true, a dot'.'
is appended toans
, andcnt
is reset to 0 to count the next three digits. -
Once the loop is broken,
return ''.join(ans[::-1])
is executed. This joins the elements ofans
together into a string, andans[::-1]
reverses the list since we built the number from the least significant digit to the most significant.
By maintaining a counter and using the divmod function to split the integer into digits, the approach avoids string-to-integer conversions except when appending digits to the answer list. The use of a list to construct the answer in reverse order helps efficiently build the result since lists in Python have a time complexity of O(1) for typical append operations. Once the number is fully converted into a list of characters, the reversal and join operations form the final string to be returned.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through the solution with a small example. Supposing the input integer n
is 12345
. We need to format it as a string with a dot inserted every three digits from the right. So, our expected output is "12.345"
.
Here are the steps demonstrating how the algorithm would process this input:
-
Initialize the counter
cnt
to 0 and the listans
to an empty list. -
Enter the loop since
n
is non-zero. -
In the first iteration,
divmod(n, 10)
gives usn = 1234
andv = 5
. We append'5'
toans
and incrementcnt
by 1. -
In the second iteration, now
n = 123
andv = 4
. We append'4'
toans
and incrementcnt
by 1. -
In the third iteration,
n = 12
andv = 3
. We append'3'
toans
.cnt
is now 3, so we append a'.'
toans
and resetcnt
to 0. -
In the fourth iteration,
n = 1
andv = 2
. We append'2'
toans
and incrementcnt
by 1. -
In the fifth iteration,
n = 0
andv = 1
. We append'1'
toans
. Sincen
is now 0, we break out of the loop. -
Now
ans
is['5', '4', '3', '.', '2', '1']
. We need to reverse the list to get the digits in the correct order. -
After reversing,
ans
is['1', '2', '.', '3', '4', '5']
. -
Joining the elements in
ans
with''
, we get the final result"12.345"
. -
We return the resulting string
"12.345"
.
Note: If n
had been smaller than 1000, say n = 12
, the process would be the same without the insertion of a dot, resulting in "12"
.
Solution Implementation
1class Solution:
2 def thousandSeparator(self, value: int) -> str:
3 # Initialize a counter to track the number of digits processed
4 digit_counter = 0
5
6 # Initialize a list to build the answer incrementally
7 result_parts = []
8
9 # Loop until the entire number has been processed
10 while True:
11 # Divide the number by 10 to get the next digit and the remainder
12 value, remainder = divmod(value, 10)
13
14 # Convert the remainder (a digit) to a string and append to the list
15 result_parts.append(str(remainder))
16
17 # Increment the digit counter
18 digit_counter += 1
19
20 # Check if the number has been completely divided
21 if value == 0:
22 break
23
24 # If three digits have been processed, insert a period and reset counter
25 if digit_counter == 3:
26 result_parts.append('.')
27 digit_counter = 0
28
29 # Since digits are processed in reverse order, reverse the list and join the parts into a string
30 formatted_number = ''.join(result_parts[::-1])
31
32 return formatted_number
33
1class Solution {
2 // This method converts an integer to a string with dot separators for every three digits
3 public String thousandSeparator(int number) {
4 int count = 0; // Initialize a counter to keep track of every three digits
5 StringBuilder formattedNumber = new StringBuilder(); // Use StringBuilder to efficiently manipulate strings
6
7 // Loop until the entire number has been processed
8 while (true) {
9 int digit = number % 10; // Extract the last digit of the number
10 number /= 10; // Remove the last digit from the number
11 formattedNumber.append(digit); // Append the digit to the StringBuilder
12 count++; // Increment the counter
13
14 // If the number is reduced to zero, break out of the loop
15 if (number == 0) {
16 break;
17 }
18
19 // After every third digit, append a dot to the StringBuilder
20 if (count == 3) {
21 formattedNumber.append('.');
22 count = 0; // Reset the counter after appending the dot
23 }
24 }
25
26 // Reverse the StringBuilder content to maintain the correct order
27 // and convert it to a String before returning
28 return formattedNumber.reverse().toString();
29 }
30}
31
1class Solution {
2public:
3 // Function to add a thousand separator in the given integer.
4 // It inserts a period '.' every three digits from right to left
5 string thousandSeparator(int n) {
6 int count = 0; // Initialize a counter to keep track of the number of digits
7 string formattedNumber; // Initialize an empty string to build the result
8
9 // Proceed to iterate until the entire number has been processed
10 do {
11 int digit = n % 10; // Extract the rightmost digit
12 n /= 10; // Remove the rightmost digit from the number
13 formattedNumber += to_string(digit); // Append the digit to the result string
14 count++; // Increment the digit counter
15
16 // Insert a period after every third digit from the right, but only if more digits are left to process
17 if (count == 3 && n != 0) {
18 formattedNumber += '.';
19 count = 0; // Reset the digit counter after inserting a period
20 }
21 } while (n != 0); // Continue as long as there are digits left
22
23 // Since the digits were added in reverse order, reverse the string to get the correct format
24 reverse(formattedNumber.begin(), formattedNumber.end());
25
26 return formattedNumber; // Return the properly formatted number
27 }
28};
29
1/**
2 * Function to add a thousand separator in the given integer.
3 * It inserts a period '.' every three digits from right to left.
4 * @param {number} n - The number in which the thousand separator must be added.
5 * @returns {string} - The number as a string with thousand separators added.
6 */
7function thousandSeparator(n: number): string {
8 let count = 0; // Initialize a counter to keep track of the number of digits.
9 let formattedNumber = ''; // Initialize an empty string to build the result.
10
11 // Proceed to iterate until the entire number has been processed.
12 do {
13 const digit = n % 10; // Extract the rightmost digit.
14 n = Math.floor(n / 10); // Remove the rightmost digit from the number.
15 formattedNumber += digit.toString(); // Append the digit to the result string.
16 count++; // Increment the digit counter.
17
18 // Insert a period after every third digit from the right, but only if more digits are left to process.
19 if (count === 3 && n !== 0) {
20 formattedNumber += '.';
21 count = 0; // Reset the digit counter after inserting a period.
22 }
23 } while (n !== 0); // Continue as long as there are digits left.
24
25 // Since the digits were added in reverse order, reverse the string to get the correct format.
26 formattedNumber = reverseString(formattedNumber);
27
28 return formattedNumber; // Return the properly formatted number.
29}
30
31/**
32 * Helper function to reverse a string.
33 * @param {string} str - The string to be reversed.
34 * @returns {string} - The reversed string.
35 */
36function reverseString(str: string): string {
37 return str.split('').reverse().join('');
38}
39
Time and Space Complexity
The time complexity of the provided code is O(d)
, where d
is the number of digits in the integer n
. This is because the while loop runs once for each digit of n
until n
becomes 0
, performing a constant amount of work inside the loop for each digit (division, modulo, and counter operations).
The space complexity is also O(d)
, as the main additional space used is the list ans
which stores each digit as a character. In the worst case, for every three digits, there is an additional period character, resulting in d/3
period characters. Thus, the total space used is proportional to the number of digits d
.
Learn more about how to find time and space complexity quickly using problem constraints.
Which algorithm should you use to find a node that is close to the root of the tree?
Recommended Readings
LeetCode Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way we
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https algomonster s3 us east 2 amazonaws com recursion jpg You first
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!