Largest Number

Updated on 04 June, 2025
Largest Number header image

Problem Statement

Given a list consisting of non-negative integers named nums, the task is to rearrange these integers to form the largest possible number. This arrangement and subsequent combination need to return a number in a string format due to potential limitations in standard numerical data types for handling very large numbers. In essence, each integer from the list must be treated as a string and concatenated in such an order that it results in the largest combined value.

Examples

Example 1

Input:

nums = [10,2]

Output:

"210"

Example 2

Input:

nums = [3,30,34,5,9]

Output:

"9534330"

Constraints

  • 1 <= nums.length <= 100
  • 0 <= nums[i] <= 109

Approach and Intuition

To solve the problem of determining the order of elements to form the largest number, let’s delve into some detailed steps and the reasoning behind them:

  1. Convert all the numbers in the list to strings. This is necessary because we need to concatenate the numbers, and string manipulation is straightforward for this operation.
  2. Sort the array, but not with a typical numerical ordering. The ordering is determined by comparing two numbers (x and y), and seeing which combination forms a higher number when placed together, i.e., comparing xy with yx.
  3. For instance, if x = '9' and y = '34', you'd compare '934' and '349' to decide the order in which to place '9' and '34'.
  4. Once the array is sorted with this custom rule, concatenate all the elements.
  5. A special case arises when the array consists solely of zeros (e.g., [0,0,0]). Here, instead of returning "000", we should return just "0".
  6. Handling large numbers: The result can be quite large, which is why the result is returned in string format to avoid overflow issues with standard integer types.

Examples from the constraints demonstrate the application of the sorting logic:

  • In example one (nums = [10,2]), the algorithm would determine that placing '2' before '10' in string format ('210') forms a larger number than placing '10' before '2' ('102'). Therefore, the result is "210".
  • Similarly, for nums = [3,30,34,5,9], the concatenation that results in the largest number is '9534330', giving the final output as "9534330".

This approach ensures that regardless of the list's size (up to 100 elements) or the individual values (up to 1 billion), we can generate the largest possible number by a methodical assessment of string combinations.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    string largestNumber(vector<int>& nums) {
        customSort(nums);
        string maxNum;
        for (int num : nums) {
            maxNum += to_string(num);
        }
        return maxNum[0] == '0' ? "0" : maxNum;
    }

private:
    const int CHUNK = 32;

    void sortedInsert(vector<int>& nums, int left, int right) {
        for (int i = left + 1; i <= right; ++i) {
            int temp = nums[i];
            int j = i - 1;
            while (j >= left && compareNumbers(temp, nums[j])) {
                nums[j + 1] = nums[j];
                --j;
            }
            nums[j + 1] = temp;
        }
    }

    void mergeGroups(vector<int>& nums, int left, int mid, int right) {
        vector<int> leftPart(nums.begin() + left, nums.begin() + mid + 1);
        vector<int> rightPart(nums.begin() + mid + 1, nums.begin() + right + 1);

        int i = 0, j = 0, k = left;
        while (i < leftPart.size() && j < rightPart.size()) {
            if (compareNumbers(leftPart[i], rightPart[j])) {
                nums[k++] = leftPart[i++];
            } else {
                nums[k++] = rightPart[j++];
            }
        }
        while (i < leftPart.size()) nums[k++] = leftPart[i++];
        while (j < rightPart.size()) nums[k++] = rightPart[j++];
    }

    void customSort(vector<int>& nums) {
        int n = nums.size();
        for (int i = 0; i < n; i += CHUNK) {
            sortedInsert(nums, i, min(i + CHUNK - 1, n - 1));
        }
        for (int size = CHUNK; size < n; size *= 2) {
            for (int left = 0; left < n; left += 2 * size) {
                int mid = left + size - 1;
                int right = min(left + 2 * size - 1, n - 1);
                if (mid < right) {
                    mergeGroups(nums, left, mid, right);
                }
            }
        }
    }

    bool compareNumbers(int x, int y) {
        return to_string(x) + to_string(y) > to_string(y) + to_string(x);
    }
};

In this solution for forming the largest number from a set of integers using C++, the Solution class is defined with a main public function and additional private utilities to achieve the task. Let's analyze the detailed steps and logic used in the code:

  1. Public Function - largestNumber:

    • This function initiates by calling the customSort method to sort the integers based on a custom comparison logic.
    • It then constructs a string, maxNum, by concatenating all integers in the sorted order.
    • Before returning maxNum, it checks if the result starts with zero (indicative of all elements being zero) and returns "0" instead, ensuring a valid number format.
  2. Private Method - customSort:

    • This sorting mechanism divides the list into smaller chunks, processed independently using the sortedInsert method. The chunk size is defined by the constant CHUNK.
    • Once individual groups are sorted, they are merged using the mergeGroups method, ensuring that the entire list eventually gets sorted.
  3. sortedInsert Method:

    • This method performs insertion sort within specified boundaries (left to right).
    • It utilizes the compareNumbers method to determine order, ensuring that the sequence maximizes the resultant concatenated number.
  4. mergeGroups Method:

    • This function merges two sorted groups using a two-pointer technique.
    • Elements from each group are competitively merged based on the compareNumbers result to ensure that the larger number stays preferable in the resultant number.
  5. compareNumbers Function:

    • This comparator defines the custom rule to arrange two integers.
    • It concatenates two numbers in both possible orders and compares them, deciding the preferred sequence based on the higher resultant string value.

This approach uses both sorting and merging techniques driven by a custom comparator that aims to maximize the value when numbers are concatenated. The use of chunks and subsequent merging ensures efficiency, especially beneficial for large lists.

java
class Solution {

    private static final int PARTITION_SIZE = 32;

    public String findMaxConcatenation(int[] array) {
        Integer[] sortedArray = Arrays.stream(array).boxed().toArray(Integer[]::new);
        customSort(sortedArray);
        StringBuilder maxNumber = new StringBuilder();
        for (int num : sortedArray) {
            maxNumber.append(num);
        }
        return maxNumber.charAt(0) == '0' ? "0" : maxNumber.toString();
    }

    private void sortSubRange(Integer[] dataArray, int start, int end) {
        for (int i = start + 1; i <= end; ++i) {
            int temporary = dataArray[i];
            int j = i - 1;
            while (j >= start && compareDescending(temporary, dataArray[j])) {
                dataArray[j + 1] = dataArray[j];
                --j;
            }
            dataArray[j + 1] = temporary;
        }
    }

    private void mergeArrays(Integer[] dataArray, int start, int middle, int end) {
        Integer[] leftSubarray = Arrays.copyOfRange(dataArray, start, middle + 1);
        Integer[] rightSubarray = Arrays.copyOfRange(dataArray, middle + 1, end + 1);

        int i = 0, j = 0, k = start;
        while (i < leftSubarray.length && j < rightSubarray.length) {
            if (compareDescending(leftSubarray[i], rightSubarray[j])) {
                dataArray[k++] = leftSubarray[i++];
            } else {
                dataArray[k++] = rightSubarray[j++];
            }
        }
        while (i < leftSubarray.length) dataArray[k++] = leftSubarray[i++];
        while (j < rightSubarray.length) dataArray[k++] = rightSubarray[j++];
    }

    private void customSort(Integer[] dataArray) {
        int len = dataArray.length;
        for (int i = 0; i < len; i += PARTITION_SIZE) {
            sortSubRange(dataArray, i, Math.min(i + PARTITION_SIZE - 1, len - 1));
        }
        for (int size = PARTITION_SIZE; size < len; size *= 2) {
            for (int start = 0; start < len; start += 2 * size) {
                int middle = start + size - 1;
                int end = Math.min(start + 2 * size - 1, len - 1);
                if (middle < end) {
                    mergeArrays(dataArray, start, middle, end);
                }
            }
        }
    }

    private boolean compareDescending(int first, int second) {
        return (Integer.toString(first) + Integer.toString(second)).compareTo(Integer.toString(second) + Integer.toString(first)) > 0;
    }
}

Given the task of generating the largest concatenated number from an array of integers, this Java implementation uses a custom sorting strategy to achieve the desired outcome. The approach involves converting the integers to strings and forming possible combinations to determine the optimal ordering which would generate the largest concatenated number. The primary steps followed in the solution are outlined below:

  • Convert the int array to an Integer array to utilize object functionalities.
  • Implement custom sorting with customSort to arrange the integers. This function modifies the integer order based on their string representations ensuring that their concatenation produces a maximal result.
  • The customSort method itself involves a hybrid of insertion sort (sortSubRange) and merge sort (mergeArrays) to manage the sorting process efficiently:
    • sortSubRange is used to sort smaller partitions of the array first, facilitating localized ordered sequences.
    • mergeArrays then combines these partitions effectively, maintaining the overall order necessary for the maximal concatenation.
  • Special consideration is given in the compareDescending method, where two numbers are compared based on their potential positions in a concatenated string. Here, the function determines which order of numbers results in a higher value when concatenated, ensuring that the higher combination precedes the other.
  • After sorting, the integers are concatenated to form the final largest number.
  • Edge cases are handled, particularly when the result could start with a zero due to the input containing zeros; in such cases, the method returns "0".

This approach ensures that the final string representation of concatenated integers is the largest possible, tailored specifically through the use of efficient sorting principles and custom comparative strategies.

python
class Solution:
    BLOCK_SIZE = 32

    def largestNumber(self, nums: List[int]) -> str:
        # Custom sorting approach
        self.sort_elements(nums)
        # Form the largest number from sorted elements
        result_number = "".join(map(str, nums))
        # Check if the result is leading zeroes
        return "0" if result_number[0] == "0" else result_number

    def sort_insert(self, elements: List[int], start: int, end: int):
        for i in range(start + 1, end + 1):
            key = elements[i]
            j = i - 1
            while j >= start and self.numerical_compare(key, elements[j]):
                elements[j + 1] = elements[j]
                j -= 1
            elements[j + 1] = key

    def combine(self, elements: List[int], start: int, middle: int, end: int):
        left_part = elements[start : middle + 1]
        right_part = elements[middle + 1 : end + 1]

        i, j, k = 0, 0, start
        while i < len(left_part) and j < len(right_part):
            if self.numerical_compare(left_part[i], right_part[j]):
                elements[k] = left_part[i]
                i += 1
            else:
                elements[k] = right_part[j]
                j += 1
            k += 1
        elements[k : end + 1] = left_part[i:] + right_part[j:]

    def sort_elements(self, elements: List[int]):
        len_elements = len(elements)
        # Insertion sort on small segments
        for i in range(0, len_elements, self.BLOCK_SIZE):
            self.sort_insert(elements, i, min(i + self.BLOCK_SIZE - 1, len_elements - 1))
        # Merging phases
        size = self.BLOCK_SIZE
        while size < len_elements:
            for start in range(0, len_elements, 2 * size):
                mid = start + size - 1
                end = min(start + 2 * size - 1, len_elements - 1)
                if mid < end:
                    self.combine(elements, start, mid, end)
            size *= 2

    def numerical_compare(self, a: int, b: int) -> bool:
        return str(a) + str(b) > str(b) + str(a)

This Python solution intends to solve the problem of forming the largest possible number from a list of integers by implementing a custom sorting mechanism followed by concatenation. Here’s an outline of the approach used in the code:

  • Custom Sorting Mechanism: The solution first sorts the integers based on a custom comparison function. The function numerical_compare determines the order of two integers a and b by comparing the concatenated string results of ab and ba to decide which combination forms a larger number.

  • Sorting Process:

    • The list of numbers is divided into blocks. Each block is independently sorted using an insertion sort mechanism defined in the sort_insert function.
    • Post sorting the blocks, a merge process is initiated using the combine function, which merges two adjacent sorted segments into a single sorted segment.
    • The merging is iteratively applied over the entire array with increasing segment sizes until the entire list is fully sorted.
  • Constructing the Result:

    • The sorted elements are concatenated into a string to form the potential largest number.
    • Additionally, the program handles cases where the resulting number might have leading zeros. It returns "0" if the sorted and concatenated result starts with '0', addressing scenarios where the list might contain multiple zeros.

The solution takes advantage of efficient hybrid sorting techniques (insertion sort for small segments and merge sort for merging) and a logical string comparison to customize the ordering of integers. This method ensures that the final string represents the largest numeric value possible.

Comments

No comments yet.