2165. Smallest Value of the Rearranged Number
Problem Description
You are given an integer num
. The task is to rearrange the digits of num
in such a way that the resulting number is the smallest possible value and doesn't have any leading zeros. Importantly, you must maintain the sign of the original number; if the input number is negative, the result should also be negative, and the same for a positive number. The requirement is to return this minimum possible rearreganged number.
Intuition
To solve this problem, we can utilize a counting sort-like approach since we're dealing with individual digits which are only from 0 to 9. Here’s the intuition broken down into steps:
-
Handling Zero: If the number is 0, return it directly since 0 cannot be rearranged to get a smaller number.
-
Digit Counting: Count how many times each digit from 0 to 9 appears in the number using a list where the index corresponds to the digit and the value at that index represents the count.
-
Handle Negative Numbers: If the number is negative, to get the smallest possible number after rearrangement, we should start the number with the largest digit available and proceed to the smallest. Since leading zeros are not allowed, we only arrange the nonzero digits.
-
Handle Positive Numbers: a. If there are any zeros (as recorded in the digit counting step), make sure to place a nonzero digit at the beginning to avoid leading zeros. This is achieved by looking for the first nonzero count from 1 to 9, adding it to the answer string, and decreasing its count. b. After placing the first nonzero digit, append the remaining digits starting from 0 to 9 to ensure a minimal value.
-
Returning the Result: Combine the arranged digits into a single integer, preserving the sign, and return this integer as the answer.
This approach effectively sorts the digits to form the smallest (or largest if negative) possible number without using any extra sorting function, and the counting steps ensure that no leading zeros will appear in the final arrangement.
Solution Approach
The solution follows a direct approach, implementing the intuition we described earlier. Here's how the code breaks down the problem and applies an algorithm to solve it:
-
Initialization and Handling of Zero:
- If
num
is 0, we return 0 immediately as we cannot rearrange it for a smaller value. - Initialize a counter array
cnt
with 10 zeroes, which will serve to count the occurrences of each digit (0-9). - Record the sign of
num
in a booleanneg
and useabs(num)
to work with the absolute value, simplifying our logic for rearrangement.
- If
-
Counting Digits:
- A while loop is used to extract each digit from
num
usingdivmod(num, 10)
, which provides quotient and remainder - the latter being the digit we're counting. - Increment the count of the extracted digit in the
cnt
array.
- A while loop is used to extract each digit from
-
Constructing the Smallest/Largest Number Based on Sign:
- Initialize an empty string
ans
to build the final digit string. - If the number is negative (
neg
isTrue
), iterate from 9 down to 0:- For each digit
i
, if the countcnt[i]
is non-zero, append the digiti
converted to a string, multiplied by its count, toans
. This assembles the largest possible number from the digits.
- For each digit
- If the number is positive (
neg
isFalse
):- First, find and place a non-zero digit if there are any zeros to avoid leading zeros. Iterate from 1 to 9 and on finding a non-zero count, append that digit to
ans
and decrement its count. - Next, append the rest of the digits in ascending order to build the smallest possible number. Iterate from 0 to 9 and for each digit
i
, if the countcnt[i]
is non-zero, append the digit multiplied by its count toans
.
- First, find and place a non-zero digit if there are any zeros to avoid leading zeros. Iterate from 1 to 9 and on finding a non-zero count, append that digit to
- Initialize an empty string
-
Finalizing the Answer:
- Since
ans
is a string, it is converted back to an integer. The sign is reintroduced by negating the result if the original number was negative.
- Since
In summary, the code uses the counting sort technique to tally the occurrences of each digit and then rearranges the digits according to whether the number is positive or negative, to return the smallest possible value without leading zeros. It leverages simple array manipulation and string concatenation to avoid more complex sorting algorithms or additional data structures.
Ready to land your dream job?
Unlock your dream job with a 2-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Consider the integer num = 310
. We need to find the smallest possible value by rearranging num
's digits without leading zeros.
-
Handling Zero:
num
is not 0, so we proceed with the solution.
-
Digit Counting:
- We count the occurrences of each digit:
3
appears once.1
appears once.0
appears once.
- The counter array
cnt
is thus[1, 1, 0, 1, 0, 0, 0, 0, 0, 0]
.
- We count the occurrences of each digit:
-
Handle Positive Numbers:
- Since
num
is positive, we follow the steps for positive numbers. a) We pick the smallest nonzero digit to avoid a leading zero. This is the digit1
. - We place
1
at the beginning, and thecnt
array updates to[1, 0, 0, 1, 0, 0, 0, 0, 0, 0]
. b) Now we append the rest of the digits sorted in ascending order. The next smallest digit is0
, followed by3
. - We append these to get the number
103
.
- Since
-
Returning the Result:
- Now, we combine the digits to form the integer
103
, which is the smallest variation of310
with no leading zero.
- Now, we combine the digits to form the integer
On the other hand, consider the integer num = -310
. For negative numbers, the smallest value is achieved by arranging digits in reverse order, from largest to smallest.
-
Handling Zero:
num
is not 0, so we proceed with the solution.
-
Digit Counting:
- The occurrences of each digit are the same as above, and the counter array
cnt
doesn't change.
- The occurrences of each digit are the same as above, and the counter array
-
Handle Negative Numbers:
- Since
num
is negative, the largest digit, which is3
, goes first, followed by1
, then0
. - We get the negative number
-310
since rearranging the digits in descending order gives the same number. We don't need to change anything for this specific example, as it is already in the required form.
- Since
Thus, by following the counting sort-like approach, we can efficiently determine the smallest possible rearrangement of num
while preserving the original sign and avoiding any leading zeros.
Solution Implementation
1class Solution:
2 def smallest_number(self, num: int) -> int:
3 # If the number is zero, just return it
4 if num == 0:
5 return 0
6
7 # Initialize a list to store the count of each digit
8 digit_count = [0] * 10
9
10 # Determine if the number is negative
11 is_negative = num < 0
12
13 # Work with the absolute value of the number
14 num = abs(num)
15
16 # Count the occurrences of each digit in the number
17 while num:
18 num, remainder = divmod(num, 10)
19 digit_count[remainder] += 1
20
21 # Create an empty string to build the answer
22 answer_str = ""
23
24 # If the number is negative, we create the largest number with its digits
25 if is_negative:
26 for i in range(9, -1, -1): # Start from 9 to 0
27 if digit_count[i]:
28 answer_str += str(i) * digit_count[i]
29 # Convert the string to a negative integer
30 return -int(answer_str)
31
32 # If the number is positive and contains zeros,
33 # place the smallest non-zero digit at the start
34 if digit_count[0]:
35 for i in range(1, 10):
36 if digit_count[i]:
37 answer_str += str(i)
38 digit_count[i] -= 1
39 break
40
41 # Append the remaining digits in ascending order
42 for i in range(10):
43 if digit_count[i]:
44 answer_str += str(i) * digit_count[i]
45
46 # Convert the string to an integer
47 return int(answer_str)
48
1class Solution {
2
3 // This method finds the smallest number that can be formed by rearranging the digits of the given number.
4 public long smallestNumber(long num) {
5 // If the number is 0, return it as the smallest number without any processing.
6 if (num == 0) {
7 return 0;
8 }
9
10 // An array to count the occurrences of each digit in the number.
11 int[] digitCounts = new int[10];
12
13 // Flag to check if the original number is negative.
14 boolean isNegative = num < 0;
15
16 // Take the absolute value in case the number is negative for ease of processing.
17 num = Math.abs(num);
18
19 // Count the occurrences of each digit in the number.
20 while (num != 0) {
21 digitCounts[(int) (num % 10)]++;
22 num /= 10;
23 }
24
25 // This will hold the smallest number that we form by rearranging the digits.
26 long result = 0;
27
28 // If the original number is negative, we want the largest absolute value,
29 // which when negated, gives the smallest possible negative number.
30 if (isNegative) {
31 // Construct the number from digits in descending order.
32 for (int i = 9; i >= 0; --i) {
33 while (digitCounts[i]-- > 0) {
34 result = result * 10 + i;
35 }
36 }
37 // Return the negated result since the original number was negative.
38 return -result;
39 }
40
41 // If number is positive and contains zeros, we must place the smallest non-zero digit at the
42 // front to get the smallest possible number, then follow with any zeros.
43 if (digitCounts[0] > 0) {
44 for (int i = 1; i < 10; ++i) {
45 if (digitCounts[i] > 0) {
46 result = result * 10 + i; // Place the smallest non-zero digit first.
47 digitCounts[i]--;
48 break; // Break after placing the first non-zero digit.
49 }
50 }
51 }
52
53 // After placing the smallest non-zero digit, place the remaining digits in ascending order.
54 for (int i = 0; i < 10; ++i) {
55 while (digitCounts[i]-- > 0) {
56 result = result * 10 + i;
57 }
58 }
59
60 // Return the final smallest number.
61 return result;
62 }
63}
64
1#include <vector>
2#include <cmath>
3
4class Solution {
5public:
6 // Function to find the smallest permutation of the given number
7 long long smallestNumber(long long num) {
8 // Return 0 if the number is already 0
9 if (num == 0) return 0;
10
11 // Vector to count the occurrences of each digit
12 std::vector<int> digitCount(10, 0);
13
14 // Check if the number is negative
15 bool isNegative = num < 0;
16
17 // Work with the absolute value of num
18 num = std::abs(num);
19
20 // Count occurrences of each digit
21 while (num) {
22 digitCount[num % 10]++;
23 num /= 10;
24 }
25
26 long long smallestNum = 0;
27
28 // If the number is negative, build the largest number possible and then add the sign
29 if (isNegative) {
30 for (int i = 9; i >= 0; --i) {
31 while (digitCount[i]--) {
32 smallestNum = smallestNum * 10 + i;
33 }
34 }
35 return -smallestNum; // Return the negative value
36 }
37
38 // If the number has zeroes, we must handle them properly to avoid leading zeroes
39 if (digitCount[0]) {
40 // Find the smallest non-zero digit to place at the beginning
41 for (int i = 1; i < 10; ++i) {
42 if (digitCount[i]) {
43 smallestNum = smallestNum * 10 + i;
44 digitCount[i]--;
45 break;
46 }
47 }
48 }
49
50 // Build the smallest number by adding digits in ascending order
51 for (int i = 0; i < 10; ++i) {
52 while (digitCount[i]--) {
53 smallestNum = smallestNum * 10 + i;
54 }
55 }
56
57 return smallestNum;
58 }
59};
60
1// Import necessary functionalities from 'math' module
2import { abs } from "math";
3
4// Function to find the smallest permutation of the given number
5function smallestNumber(num: number): number {
6 // Return 0 if the number is already 0
7 if (num === 0) return 0;
8
9 // Array to count the occurrences of each digit
10 let digitCount: number[] = Array(10).fill(0);
11
12 // Check if the number is negative
13 let isNegative: boolean = num < 0;
14
15 // Work with the absolute value of num
16 num = abs(num);
17
18 // Count occurrences of each digit
19 while (num > 0) {
20 digitCount[num % 10]++;
21 num = Math.floor(num / 10);
22 }
23
24 // Variable to hold the smallest (or largest if negative) permutation of the number
25 let smallestNum: number = 0;
26
27 // If the number is negative, build the largest number possible and then add the sign
28 if (isNegative) {
29 for (let i = 9; i >= 0; --i) {
30 while (digitCount[i] > 0) {
31 smallestNum = smallestNum * 10 + i;
32 digitCount[i]--;
33 }
34 }
35 // Return the negative value, as the original number was negative
36 return -smallestNum;
37 }
38
39 // If the number has zeroes, we must handle them properly to avoid leading zeroes
40 if (digitCount[0] > 0) {
41 // Find the smallest non-zero digit to place at the beginning
42 for (let i = 1; i < 10; ++i) {
43 if (digitCount[i] > 0) {
44 smallestNum = smallestNum * 10 + i;
45 digitCount[i]--;
46 break;
47 }
48 }
49 }
50
51 // Build the smallest number by adding digits in ascending order
52 for (let i = 0; i < 10; ++i) {
53 while (digitCount[i] > 0) {
54 smallestNum = smallestNum * 10 + i;
55 digitCount[i]--;
56 }
57 }
58
59 // Return the smallest permutation of the original number
60 return smallestNum;
61}
62
Time and Space Complexity
The time complexity of the provided solution is O(n + 10)
which simplifies to O(n)
where n
represents the number of digits in the integer num
. This is because we first iterate through all digits of the input num
to count them (which contributes to O(n)
), and then we iterate through the count array of 10 digits (which contributes to O(10)
but constants are omitted in Big O notation).
The space complexity of the solution is O(10)
, which simplifies to O(1)
- constant space complexity. This is because the count array cnt
has a fixed size of 10, regardless of the size of num
. The string ans
also doesn't count towards space complexity in this analysis as it simply corresponds to the size of the output, which is not considered additional space used by the algorithm.
Learn more about how to find time and space complexity quickly using problem constraints.
What does the following code do?
1def f(arr1, arr2):
2 i, j = 0, 0
3 new_arr = []
4 while i < len(arr1) and j < len(arr2):
5 if arr1[i] < arr2[j]:
6 new_arr.append(arr1[i])
7 i += 1
8 else:
9 new_arr.append(arr2[j])
10 j += 1
11 new_arr.extend(arr1[i:])
12 new_arr.extend(arr2[j:])
13 return new_arr
14
1public static List<Integer> f(int[] arr1, int[] arr2) {
2 int i = 0, j = 0;
3 List<Integer> newArr = new ArrayList<>();
4
5 while (i < arr1.length && j < arr2.length) {
6 if (arr1[i] < arr2[j]) {
7 newArr.add(arr1[i]);
8 i++;
9 } else {
10 newArr.add(arr2[j]);
11 j++;
12 }
13 }
14
15 while (i < arr1.length) {
16 newArr.add(arr1[i]);
17 i++;
18 }
19
20 while (j < arr2.length) {
21 newArr.add(arr2[j]);
22 j++;
23 }
24
25 return newArr;
26}
27
1function f(arr1, arr2) {
2 let i = 0, j = 0;
3 let newArr = [];
4
5 while (i < arr1.length && j < arr2.length) {
6 if (arr1[i] < arr2[j]) {
7 newArr.push(arr1[i]);
8 i++;
9 } else {
10 newArr.push(arr2[j]);
11 j++;
12 }
13 }
14
15 while (i < arr1.length) {
16 newArr.push(arr1[i]);
17 i++;
18 }
19
20 while (j < arr2.length) {
21 newArr.push(arr2[j]);
22 j++;
23 }
24
25 return newArr;
26}
27
Recommended Readings
Math for Technical Interviews How much math do I need to know for technical interviews The short answer is about high school level math Computer science is often associated with math and some universities even place their computer science department under the math faculty However the reality is that you
Sorting Summary Comparisons We presented quite a few sorting algorithms and it is essential to know the advantages and disadvantages of each one The basic algorithms are easy to visualize and easy to learn for beginner programmers because of their simplicity As such they will suffice if you don't know any advanced
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
Want a Structured Path to Master System Design Too? Don’t Miss This!