Facebook Pixel

3309. Maximum Possible Number by Binary Concatenation

MediumBit ManipulationArrayEnumeration
Leetcode Link

Problem Description

You have an array nums containing exactly 3 integers.

Your task is to find the maximum possible number that can be created by:

  1. Converting each integer in nums to its binary representation (without leading zeros)
  2. Concatenating these binary representations in some order
  3. Converting the resulting binary string back to a decimal number

For example, if you have numbers like 1, 2, and 3:

  • 1 in binary is "1"
  • 2 in binary is "10"
  • 3 in binary is "11"

You can arrange these binary strings in different orders like "11011" (from 1,10,11) or "11110" (from 11,1,10) or "10111" (from 10,1,11), etc. Each arrangement gives a different decimal value when converted back.

The solution works by trying all 6 possible permutations of the 3 numbers (since 3! = 6). For each permutation:

  • Convert each number to its binary string using bin(i)[2:] (the [2:] removes the '0b' prefix)
  • Join all binary strings together
  • Convert the concatenated binary string to decimal using int(..., 2)
  • Track the maximum value found

The function returns the largest decimal number that can be formed through any arrangement of the binary representations.

Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

Intuition

When we concatenate binary strings, we want the resulting binary number to be as large as possible. In binary, a number is larger when it has more significant bits set to 1 in the leftmost positions.

Since we're dealing with only 3 numbers, the brute force approach becomes feasible. With just 3 elements, there are only 3! = 6 possible arrangements to check. This small number of possibilities makes it practical to simply try all permutations and pick the maximum.

The key insight is that the optimal ordering isn't immediately obvious from just looking at the decimal values. For instance, if we have numbers 2 ("10"), 8 ("1000"), and 10 ("1010"), the arrangement that produces the maximum isn't necessarily in descending order of the original numbers. We need to consider how the binary representations concatenate together.

When we concatenate "10" + "1000" we get "101000" (which is 40 in decimal), but if we concatenate "1000" + "10" we get "100010" (which is 34 in decimal). The first arrangement is better even though we put the smaller number first.

Since determining the optimal order requires considering the actual binary concatenations and there's no simple rule to determine the best order without trying the combinations, the most straightforward approach is to generate all permutations, compute the resulting decimal value for each, and return the maximum. The small fixed size of the input (always 3 elements) makes this exhaustive search both simple and efficient.

Solution Approach

The solution uses a brute force enumeration approach with Python's permutations function from the itertools module.

Step-by-step implementation:

  1. Initialize the maximum value: Start with ans = 0 to track the maximum decimal number found.

  2. Generate all permutations: Use permutations(nums) to generate all 6 possible orderings of the 3 numbers. For example, if nums = [1, 2, 3], it generates:

    • (1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)
  3. Process each permutation: For each arrangement arr:

    • Convert each number to binary using bin(i)[2:]
      • bin(i) returns a string like "0b101"
      • [2:] slices off the "0b" prefix, leaving just "101"
    • Join all binary strings together using "".join(...)
    • Convert the concatenated binary string to decimal using int(..., 2) where the second parameter 2 indicates base-2 (binary)
  4. Track the maximum: Compare each resulting decimal number with the current maximum using ans = max(ans, num).

  5. Return the result: After checking all permutations, return the maximum value found.

Example walkthrough:

If nums = [1, 2, 3]:

  • Permutation (1, 2, 3): "1" + "10" + "11" = "11011" → 27 in decimal
  • Permutation (3, 2, 1): "11" + "10" + "1" = "11101" → 29 in decimal
  • And so on for all 6 permutations...

The algorithm would return 30, which comes from the arrangement that produces "11110" in binary.

The time complexity is O(1) since we always have exactly 3 elements and 6 permutations to check. The space complexity is also O(1) as we only store a fixed amount of data regardless of the input values.

Ready to land your dream job?

Unlock your dream job with a 5-minute evaluator for a personalized learning plan!

Start Evaluator

Example Walkthrough

Let's walk through the solution with nums = [2, 8, 10]:

Step 1: Convert each number to binary

  • 2 → "10"
  • 8 → "1000"
  • 10 → "1010"

Step 2: Try all 6 permutations and calculate their decimal values

  1. (2, 8, 10): "10" + "1000" + "1010" = "1010001010"

    • Converting "1010001010" to decimal: 650
  2. (2, 10, 8): "10" + "1010" + "1000" = "1010101000"

    • Converting "1010101000" to decimal: 680
  3. (8, 2, 10): "1000" + "10" + "1010" = "1000101010"

    • Converting "1000101010" to decimal: 554
  4. (8, 10, 2): "1000" + "1010" + "10" = "100010101"0

    • Converting "10001010010" to decimal: 1106
  5. (10, 2, 8): "1010" + "10" + "1000" = "1010101000"

    • Converting "1010101000" to decimal: 680
  6. (10, 8, 2): "1010" + "1000" + "10" = "101010001"0

    • Converting "10101000010" to decimal: 1346

Step 3: Find the maximum Comparing all results: 650, 680, 554, 1106, 680, 1346

The maximum value is 1346, which comes from the arrangement (10, 8, 2).

This demonstrates why we need to check all permutations - the optimal order isn't intuitive and doesn't follow the original decimal ordering of the numbers.

Solution Implementation

1from typing import List
2from itertools import permutations
3
4class Solution:
5    def maxGoodNumber(self, nums: List[int]) -> int:
6        """
7        Find the maximum number that can be formed by concatenating 
8        the binary representations of the numbers in different orders.
9      
10        Args:
11            nums: List of integers to concatenate in binary form
12          
13        Returns:
14            Maximum possible integer value after binary concatenation
15        """
16        max_value = 0
17      
18        # Try all possible permutations of the input numbers
19        for permutation in permutations(nums):
20            # Convert each number to binary (removing '0b' prefix) 
21            # and concatenate them
22            binary_string = "".join(bin(num)[2:] for num in permutation)
23          
24            # Convert the concatenated binary string back to decimal
25            decimal_value = int(binary_string, 2)
26          
27            # Update maximum value found so far
28            max_value = max(max_value, decimal_value)
29      
30        return max_value
31
1class Solution {
2    // Array to store input numbers
3    private int[] nums;
4
5    /**
6     * Finds the maximum number that can be formed by concatenating 
7     * the binary representations of three numbers in any order.
8     * 
9     * @param nums Array containing exactly 3 integers
10     * @return The maximum decimal value formed by binary concatenation
11     */
12    public int maxGoodNumber(int[] nums) {
13        // Store the input array in instance variable
14        this.nums = nums;
15      
16        // Try all 6 possible permutations of 3 numbers (3! = 6)
17        // and find the maximum value
18        int maxValue = f(0, 1, 2);  // Permutation: nums[0], nums[1], nums[2]
19        maxValue = Math.max(maxValue, f(0, 2, 1));  // Permutation: nums[0], nums[2], nums[1]
20        maxValue = Math.max(maxValue, f(1, 0, 2));  // Permutation: nums[1], nums[0], nums[2]
21        maxValue = Math.max(maxValue, f(1, 2, 0));  // Permutation: nums[1], nums[2], nums[0]
22        maxValue = Math.max(maxValue, f(2, 0, 1));  // Permutation: nums[2], nums[0], nums[1]
23        maxValue = Math.max(maxValue, f(2, 1, 0));  // Permutation: nums[2], nums[1], nums[0]
24      
25        return maxValue;
26    }
27
28    /**
29     * Helper method to concatenate binary representations of three numbers
30     * and convert the result back to decimal.
31     * 
32     * @param i Index of first number in nums array
33     * @param j Index of second number in nums array
34     * @param k Index of third number in nums array
35     * @return Decimal value of concatenated binary strings
36     */
37    private int f(int i, int j, int k) {
38        // Convert each number to its binary string representation
39        String firstBinary = Integer.toBinaryString(nums[i]);
40        String secondBinary = Integer.toBinaryString(nums[j]);
41        String thirdBinary = Integer.toBinaryString(nums[k]);
42      
43        // Concatenate the binary strings and parse as binary to get decimal value
44        String concatenatedBinary = firstBinary + secondBinary + thirdBinary;
45        return Integer.parseInt(concatenatedBinary, 2);
46    }
47}
48
1class Solution {
2public:
3    int maxGoodNumber(vector<int>& nums) {
4        int maxResult = 0;
5      
6        // Lambda function to convert array of numbers to a single integer
7        // by concatenating their binary representations
8        auto concatenateBinary = [&](vector<int>& nums) {
9            int result = 0;
10            vector<int> binaryDigits;
11          
12            // Extract all binary digits from each number in the array
13            for (int num : nums) {
14                // Convert each number to binary and store digits in reverse order
15                while (num > 0) {
16                    binaryDigits.push_back(num & 1);  // Get least significant bit
17                    num >>= 1;  // Right shift to process next bit
18                }
19            }
20          
21            // Reconstruct the number from binary digits (stored in reverse)
22            while (!binaryDigits.empty()) {
23                result = result * 2 + binaryDigits.back();  // Build number from MSB to LSB
24                binaryDigits.pop_back();
25            }
26          
27            return result;
28        };
29      
30        // Try all possible permutations of the array (3! = 6 permutations for 3 elements)
31        for (int i = 0; i < 6; ++i) {
32            // Calculate the concatenated binary value for current permutation
33            maxResult = max(maxResult, concatenateBinary(nums));
34            // Generate next permutation
35            next_permutation(nums.begin(), nums.end());
36        }
37      
38        return maxResult;
39    }
40};
41
1/**
2 * Finds the maximum number that can be formed by concatenating 
3 * the binary representations of three numbers in any order
4 * @param nums - Array containing exactly 3 numbers
5 * @returns The maximum decimal value after binary concatenation
6 */
7function maxGoodNumber(nums: number[]): number {
8    /**
9     * Concatenates binary representations of three numbers at given indices
10     * and converts the result back to decimal
11     * @param firstIndex - Index of the first number
12     * @param secondIndex - Index of the second number  
13     * @param thirdIndex - Index of the third number
14     * @returns Decimal value of concatenated binary strings
15     */
16    const concatenateBinaryNumbers = (
17        firstIndex: number, 
18        secondIndex: number, 
19        thirdIndex: number
20    ): number => {
21        // Convert each number to its binary string representation
22        const firstBinary: string = nums[firstIndex].toString(2);
23        const secondBinary: string = nums[secondIndex].toString(2);
24        const thirdBinary: string = nums[thirdIndex].toString(2);
25      
26        // Concatenate binary strings and convert back to decimal
27        const concatenatedBinary: string = firstBinary + secondBinary + thirdBinary;
28        const decimalResult: number = parseInt(concatenatedBinary, 2);
29      
30        return decimalResult;
31    };
32
33    // Try all 6 possible permutations of the 3 numbers
34    let maximumValue: number = concatenateBinaryNumbers(0, 1, 2);
35    maximumValue = Math.max(maximumValue, concatenateBinaryNumbers(0, 2, 1));
36    maximumValue = Math.max(maximumValue, concatenateBinaryNumbers(1, 0, 2));
37    maximumValue = Math.max(maximumValue, concatenateBinaryNumbers(1, 2, 0));
38    maximumValue = Math.max(maximumValue, concatenateBinaryNumbers(2, 0, 1));
39    maximumValue = Math.max(maximumValue, concatenateBinaryNumbers(2, 1, 0));
40
41    return maximumValue;
42}
43

Time and Space Complexity

The time complexity is O(n! × n × log M), where n is the length of the nums array (which is 3 based on the problem context) and M represents the maximum value of the elements in nums. Breaking this down:

  • permutations(nums) generates n! permutations
  • For each permutation, we iterate through n elements to build the binary string
  • Converting each number to binary using bin(i)[2:] takes O(log M) time
  • The int(..., 2) conversion also takes O(n × log M) time for the concatenated binary string

Since n = 3 is a constant, the time complexity simplifies to O(log M).

The space complexity is O(n × log M) for storing the concatenated binary string during each iteration. However, since n = 3 is constant and we're not storing all permutations simultaneously, the space complexity simplifies to O(log M). If we consider only the extra space beyond the input, it can be considered O(1) when treating the maximum binary representation length as a constant factor.

Learn more about how to find time and space complexity quickly.

Common Pitfalls

1. String Concatenation Order Confusion

A common mistake is assuming that lexicographically larger binary strings will always produce larger decimal values when concatenated. This isn't true because the position of bits matters significantly in the final decimal value.

Incorrect Assumption:

# Wrong: Trying to sort binary strings lexicographically
def maxGoodNumber(self, nums: List[int]) -> int:
    binaries = [bin(num)[2:] for num in nums]
    binaries.sort(reverse=True)  # This doesn't guarantee maximum decimal
    return int("".join(binaries), 2)

Why it fails: Consider nums = [1, 2, 3]:

  • Sorting binary strings: ["11", "10", "1"]"11101" = 29
  • But ["11", "1", "10"]"11110" = 30 (which is larger!)

2. Custom Comparator Pitfall

Another flawed approach is using a custom comparator to sort numbers based on their concatenated binary values:

Incorrect Implementation:

# Wrong: Simple comparison of concatenated pairs
def maxGoodNumber(self, nums: List[int]) -> int:
    nums.sort(key=lambda x: bin(x)[2:], reverse=True)
    binary = "".join(bin(num)[2:] for num in nums)
    return int(binary, 2)

Correct Approach with Custom Comparator:

from functools import cmp_to_key

def maxGoodNumber(self, nums: List[int]) -> int:
    def compare(x, y):
        # Compare which order produces a larger binary number
        bin_x, bin_y = bin(x)[2:], bin(y)[2:]
        if bin_x + bin_y > bin_y + bin_x:
            return -1  # x should come before y
        elif bin_x + bin_y < bin_y + bin_x:
            return 1   # y should come before x
        else:
            return 0   # order doesn't matter
  
    nums.sort(key=cmp_to_key(compare))
    binary_string = "".join(bin(num)[2:] for num in nums)
    return int(binary_string, 2)

3. Overlooking Edge Cases with Zero

If the array contains 0, its binary representation is just "0", which acts as padding when placed in the middle or beginning:

Example: nums = [0, 1, 2]

  • [1, 2, 0]"1" + "10" + "0" = "1100" = 12
  • [2, 1, 0]"10" + "1" + "0" = "1010" = 10
  • Always place zeros at the end for maximum value!

4. Integer Overflow Concerns

While Python handles arbitrary precision integers automatically, in other languages you might encounter overflow:

Prevention Strategy:

  • Check the maximum possible binary string length: with 3 numbers each up to 10^9, the binary representation can be quite long
  • In languages like Java or C++, use appropriate data types (long long in C++, Long in Java)
  • Consider using string comparison if the result might exceed integer limits

Example validation:

def maxGoodNumber(self, nums: List[int]) -> int:
    max_value = 0
  
    for permutation in permutations(nums):
        binary_string = "".join(bin(num)[2:] for num in permutation)
      
        # Optional: Check for potential overflow in other languages
        if len(binary_string) > 64:  # Would overflow in 64-bit systems
            # Handle appropriately based on requirements
            pass
      
        decimal_value = int(binary_string, 2)
        max_value = max(max_value, decimal_value)
  
    return max_value
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Tailor Your Study Plan:

A person thinks of a number between 1 and 1000. You may ask any number questions to them, provided that the question can be answered with either "yes" or "no".

What is the minimum number of questions you needed to ask so that you are guaranteed to know the number that the person is thinking?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More