HomeLeetcode321. Create Maximum Number - Leetcode Solutions

321. Create Maximum Number – Leetcode Solutions

Description

You are given two integer arrays nums1 and nums2 of lengths m and n respectively. nums1 and nums2 represent the digits of two numbers. You are also given an integer k.

Create the maximum number of length k <= m + n from digits of the two numbers. The relative order of the digits from the same array must be preserved.

Return an array of the k digits representing the answer.

Examples:

Example 1:

Input: nums1 = [3,4,6,5], nums2 = [9,1,2,5,8,3], k = 5
Output: [9,8,6,5,3]

Example 2:

Input: nums1 = [6,7], nums2 = [6,0,4], k = 5
Output: [6,7,6,0,4]

Example 3:

Input: nums1 = [3,9], nums2 = [8,9], k = 3
Output: [9,8,9]

Solution in Python

Approach:

  1. Subproblems: The first step is to break the problem down into smaller parts:
    • Select i digits from nums1.
    • Select k - i digits from nums2.
    • Merge the two selected parts into one array while maintaining relative order.
  2. Greedy Strategy: To form the maximum number, we need to select the largest possible subsequence of a given length from each array. This can be done using a greedy approach where we discard smaller elements to maximize the chosen subsequence.
  3. Merge Function: Once we have subsequences from nums1 and nums2, we merge them while ensuring that the resulting sequence is lexicographically the largest.
Python
class Solution:
    def maxNumber(self, nums1, nums2, k):
        # Helper function to get the maximum subsequence of length 'length' from nums
        def get_max_subsequence(nums, length):
            drop = len(nums) - length  # Number of elements we can drop
            stack = []
            for num in nums:
                # Discard smaller elements to make room for larger ones
                while drop > 0 and stack and stack[-1] < num:
                    stack.pop()
                    drop -= 1
                stack.append(num)
            # Return the largest subsequence of the required length
            return stack[:length]
        
        # Helper function to merge two subsequences into the largest possible sequence
        def merge(subseq1, subseq2):
            return [max(subseq1, subseq2).pop(0) for _ in range(len(subseq1) + len(subseq2))]
        
        # Result to store the maximum number formed
        max_num = []
        
        # Try all possible splits where i elements are taken from nums1 and (k - i) from nums2
        for i in range(max(0, k - len(nums2)), min(k, len(nums1)) + 1):
            subseq1 = get_max_subsequence(nums1, i)  # Max subsequence of length i from nums1
            subseq2 = get_max_subsequence(nums2, k - i)  # Max subsequence of length k-i from nums2
            # Merge the subsequences and check if the result is better
            max_num = max(max_num, merge(subseq1, subseq2))
        
        return max_num

Explanation:

  1. get_max_subsequence(nums, length):
    • This function extracts the largest subsequence of a given length from the array nums using a greedy approach.
    • It uses a stack to maintain the subsequence and ensures that we discard the smallest possible elements to make room for larger elements.
  2. merge(subseq1, subseq2):
    • This function merges two subsequences (subseq1 and subseq2) into the largest possible sequence. It repeatedly picks the larger of the two front elements (lexicographically) and appends it to the result.
  3. Main Loop:
    • We loop over all possible ways to split the digits between the two arrays. For each split, we calculate the best subsequence from nums1 and nums2 and merge them.
    • The result is compared to the current maximum sequence, and we keep track of the best one.
  4. Time Complexity:
    • The time complexity of the algorithm is O(k * (m + n)), where m is the length of nums1 and n is the length of nums2. This is because for each possible split, we extract subsequences and merge them, which takes linear time.

Solution in C++

C++
#include <vector>
#include <algorithm>

using namespace std;

class Solution {
public:
    // Function to find the maximum subsequence of length t from the input array
    vector<int> maxSubsequence(vector<int>& nums, int t) {
        vector<int> result;
        int toRemove = nums.size() - t; // Calculate how many elements can be removed

        // Iterate through the array and construct the maximum subsequence
        for (int num : nums) {
            // Remove elements from the result if they are smaller than the current element
            // and we still have elements to remove
            while (!result.empty() && result.back() < num && toRemove > 0) {
                result.pop_back();
                toRemove--;
            }
            result.push_back(num);
        }

        // We may have extra elements if we didn't remove enough, so resize the vector
        result.resize(t);
        return result;
    }

    // Function to merge two subsequences into the largest possible sequence
    vector<int> merge(vector<int>& nums1, vector<int>& nums2) {
        vector<int> merged;

        // Compare two sequences lexicographically and choose the larger one element by element
        while (!nums1.empty() || !nums2.empty()) {
            if (nums1 > nums2) {
                merged.push_back(nums1.front());
                nums1.erase(nums1.begin());
            } else {
                merged.push_back(nums2.front());
                nums2.erase(nums2.begin());
            }
        }
        return merged;
    }

    // Main function to find the maximum number of length k from nums1 and nums2
    vector<int> maxNumber(vector<int>& nums1, vector<int>& nums2, int k) {
        vector<int> maxResult;

        // Try all possible ways of splitting the subsequences from nums1 and nums2
        for (int i = max(0, k - (int)nums2.size()); i <= min(k, (int)nums1.size()); i++) {
            vector<int> subseq1 = maxSubsequence(nums1, i);          // Get the best subsequence of length i from nums1
            vector<int> subseq2 = maxSubsequence(nums2, k - i);      // Get the best subsequence of length k - i from nums2
            vector<int> candidate = merge(subseq1, subseq2);         // Merge the two subsequences
            
            // Update the result if the current candidate is better
            if (candidate > maxResult) {
                maxResult = candidate;
            }
        }

        return maxResult;  // Return the best possible sequence
    }
};

Solution in Javascript

JavaScript
var maxNumber = function(nums1, nums2, k) {
    // Function to get the maximum subarray of length "len" from nums
    const maxSubarray = (nums, len) => {
        let stack = [];
        let drop = nums.length - len; // Number of elements we can drop to get the subarray of size "len"
        
        for (let num of nums) {
            // If the current number is greater than the top of the stack and we can drop more elements, pop the stack
            while (drop > 0 && stack.length > 0 && stack[stack.length - 1] < num) {
                stack.pop();
                drop--;
            }
            stack.push(num);
        }
        // Only keep the first "len" elements in the stack, as it may have extra elements
        return stack.slice(0, len);
    };

    // Function to merge two subarrays to form the maximum number
    const merge = (sub1, sub2) => {
        let result = [];
        while (sub1.length || sub2.length) {
            // Compare the arrays lexicographically. If sub1 > sub2, take from sub1, else from sub2
            if (sub1 > sub2) {
                result.push(sub1.shift());
            } else {
                result.push(sub2.shift());
            }
        }
        return result;
    };

    let maxResult = [];
    
    // Try all possible splits of k between nums1 and nums2
    // i is the number of elements to take from nums1, and the rest will be taken from nums2
    for (let i = Math.max(0, k - nums2.length); i <= Math.min(k, nums1.length); i++) {
        let sub1 = maxSubarray(nums1, i);         // Get the best i-length subarray from nums1
        let sub2 = maxSubarray(nums2, k - i);     // Get the best (k - i)-length subarray from nums2
        let candidate = merge(sub1, sub2);        // Merge the two subarrays
        
        // Compare the current candidate with the best result so far, and update if it's better
        if (candidate > maxResult) {
            maxResult = candidate;
        }
    }
    
    return maxResult;
};

Solution in Java

Java
class Solution {
    
    // Main function to find the maximum number of length k
    public int[] maxNumber(int[] nums1, int[] nums2, int k) {
        int m = nums1.length;
        int n = nums2.length;
        
        // Result array to store the final output
        int[] result = new int[k];
        
        // Try to pick i digits from nums1 and (k - i) digits from nums2
        for (int i = Math.max(0, k - n); i <= Math.min(k, m); i++) {
            // Get the maximum subsequence of length i from nums1
            int[] subsequence1 = maxSubsequence(nums1, i);
            
            // Get the maximum subsequence of length (k - i) from nums2
            int[] subsequence2 = maxSubsequence(nums2, k - i);
            
            // Merge both subsequences to form the largest possible number
            int[] candidate = merge(subsequence1, subsequence2);
            
            // Compare the candidate number with the current result
            if (greater(candidate, 0, result, 0)) {
                result = candidate; // Update result if candidate is greater
            }
        }
        return result; // Return the largest number of length k
    }
    
    // Helper function to find the maximum subsequence of length len from an array
    private int[] maxSubsequence(int[] nums, int len) {
        int[] subsequence = new int[len];
        int index = 0;
        int drop = nums.length - len; // Number of digits we can drop
        
        for (int num : nums) {
            // Greedily pick the largest digits while maintaining the order
            while (index > 0 && drop > 0 && subsequence[index - 1] < num) {
                index--; // Drop the smaller element
                drop--;
            }
            if (index < len) {
                subsequence[index++] = num; // Add the current digit to the subsequence
            } else {
                drop--; // Drop the current digit if we already have enough
            }
        }
        return subsequence;
    }
    
    // Helper function to merge two subsequences into the largest possible number
    private int[] merge(int[] nums1, int[] nums2) {
        int[] merged = new int[nums1.length + nums2.length];
        int i = 0, j = 0, k = 0;
        
        // Compare elements from both subsequences and pick the larger one
        while (i < nums1.length || j < nums2.length) {
            if (greater(nums1, i, nums2, j)) {
                merged[k++] = nums1[i++];
            } else {
                merged[k++] = nums2[j++];
            }
        }
        return merged;
    }
    
    // Helper function to compare two subsequences starting from indices i and j
    private boolean greater(int[] nums1, int i, int[] nums2, int j) {
        while (i < nums1.length && j < nums2.length && nums1[i] == nums2[j]) {
            i++;
            j++;
        }
        // Return true if nums1 is greater starting from index i, otherwise false
        return j == nums2.length || (i < nums1.length && nums1[i] > nums2[j]);
    }
}

Subscribe
Notify of

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments

Popular