Construct Smallest Number From DI String

Updated on 08 May, 2025
Construct Smallest Number From DI String header image

Problem Statement

Given a pattern string indexed from zero consisting exclusively of letters 'I' (for "increasing") and 'D' (for "decreasing"), the challenge is to construct a numeric string num that is also zero-indexed and has a length of n + 1, where n is the length of the pattern. The characters in num are consecutive digits ranging from '1' to '9', used at most once per digit. The rules are straightforward: if an index i in the pattern contains 'I', the corresponding position in num must have a value less than the value at position i+1. Conversely, if an index i in the pattern contains 'D', the value at position i in num must be greater than the one at position i+1. The task is to determine the lexicographically smallest num that fits these rules.

Examples

Example 1

Input:

pattern = "IIIDIDDD"

Output:

"123549876"

Explanation:

At indices 0, 1, 2, and 4 we must have that num[i] < num[i+1].
At indices 3, 5, 6, and 7 we must have that num[i] > num[i+1].
Some possible values of num are "245639871", "135749862", and "123849765".
It can be proven that "123549876" is the smallest possible num that meets the conditions.
Note that "123414321" is not possible because the digit '1' is used more than once.

Example 2

Input:

pattern = "DDD"

Output:

"4321"

Explanation:

Some possible values of num are "9876", "7321", and "8742".
It can be proven that "4321" is the smallest possible num that meets the conditions.

Constraints

  • 1 <= pattern.length <= 8
  • pattern consists of only the letters 'I' and 'D'.

Approach and Intuition

The essence of this problem lies in determining a sequence of digits that strictly follow the increase or decrease rules dictated by each character in the pattern string, and ensuring that the resultant numeric string is the smallest in lexicographical order. Here's a structured approach to achieve this:

  1. Identify and record the length of consecutive 'I's or 'D's in the pattern. This helps in understanding the required sequence of increasing or decreasing digits.
  2. For a sequence of consecutive 'I's lasting k indices, you would ideally select the smallest k+1 available digits in increasing order. For example, if pattern has 'III', and considering smallest unused digits are from 1, the sequence would be 1234, where 1 is the smallest available digit and meets the pattern criteria.
  3. For a sequence of consecutive 'D's lasting k indices, select the smallest k+1 digits but arrange them in decreasing order. If 'DDD' is the pattern portion, and considering the smallest unused digits from 4 (if 1, 2, and 3 were already used as per prior steps), using 654 would be ideal.
  4. An important aspect is the transition between 'I' and 'D' or vice versa. If the pattern switches from 'I' to 'D', you'd need to ensure the last digit used in the increasing sequence is less than the first digit of the subsequent decreasing sequence.
  5. With every digit choice, care must be taken to ensure the digit hasn't already been used, preserving the rule that each digit from '1' to '9' can be used at most once.
  6. These steps help construct the sequence from left to right, continually adjusting as needed to adhere both to the 'I' and 'D' patterns and to ensure the smallest numerical value is achieved.

This logical, step-by-step strategy assures adherence to the constraints and patterns while also aiming for the lexicographical minimization of the string num.

Solutions

  • C++
  • Java
  • Python
cpp
class Solution {
public:
    string minNumberFromString(string sequence) {
        int sequenceLen = sequence.size();
        int peak = 0, highest = 0, digit;

        vector<int> decrementSeq(sequenceLen + 1, 0);

        for (int i = sequenceLen - 1; i >= 0; --i) {
            if (sequence[i] == 'D')
                decrementSeq[i] = decrementSeq[i + 1] + 1;
        }

        string smallestNum = "";

        for (int idx = 0; idx <= sequenceLen; idx++) {
            if (sequence[idx] == 'I') {
                peak++;
                smallestNum += '0' + peak;
                peak = max(peak, highest);
                highest = 0;
            } else {
                digit = 1 + peak + decrementSeq[idx];
                smallestNum += '0' + digit;
                highest = max(highest, digit);
            }
        }

        return smallestNum;
    }
};

The provided C++ solution constructs the smallest possible number from a given "DI" sequence where 'D' represents a decreasing step and 'I' an increasing step. The key steps involved in the implementation include:

  • Initialize a vector<int> to store the counts of consecutive 'D's starting from the end of the sequence moving to the beginning.
  • Iterate through the input sequence and construct the smallest number:
    • For 'I', increase the peak value, append it to the result, and update the highest reached peak after each 'I'.
    • For 'D', compute the appropriate number considering the peak and the count of 'D's remaining, append this value, and update the highest digit observed.
  • Return the constructed smallest number.

The algorithm accurately follows the pattern of 'D's and 'I's by adjusting the numerical value we append to our resulting string based on previous values and the requirement specified by the sequence. This method ensures the lexicographically smallest number adhering to the sequence rules.

Key considerations include handling changes in peak values effectively and adjusting to the highest value encountered so far, especially after sequences of 'D's to ensure the increment ('I') appropriately reflects a reset in trend. This careful handling of sequence dynamics and values contributes to the correctness and efficiency of the solution.

java
class Solution {

    public String generateSmallestPattern(String seq) {
        int length = seq.length();
        int highest = 0, tempMax = 0, tmp;

        // Array for storing sequences of decreases
        int[] decrementSequence = new int[length + 2];

        // Calculating the length of each decrement sequence in the pattern
        for (int index = length; index >= 0; index--) {
            if (index < length && seq.charAt(index) == 'D') decrementSequence[index] = decrementSequence[index + 1] + 1;
        }

        StringBuilder output = new StringBuilder();

        // Constructing the output based on the input sequence
        for (int i = 0; i <= length; i++) {
            if (i < length && seq.charAt(i) == 'I') {
                // Process 'I' by incrementing to the next unique maximum
                highest++;
                output.append(highest);

                // Update maximum encountered
                highest = Math.max(highest, tempMax);

                // Reset for next iteration
                tempMax = 0;
            } else {
                // Handle 'D' by using decremented sequence values
                tmp = 1 + highest + decrementSequence[i];
                output.append(tmp);

                // Update temporary max
                tempMax = Math.max(tempMax, tmp);
            }
        }

        return output.toString();
    }
}

Given the challenge of constructing the smallest lexicographical number from a string pattern of "D" and "I" characters where "D" stands for decreasing and "I" stands for increasing, this Java solution efficiently tackles the problem using a sequence-based approach. Here is a concise explanation of the provided solution:

  • Initialize necessary variables to track the highest number used (highest), a temporary maximum (tempMax), and temporary calculations (tmp).
  • Create an integer array decrementSequence to store the length of consecutive "D" sequences, essentially how many places the sequence will decrement.
  • Populate decrementSequence by iterating backwards through the input pattern, ensuring each "D" contributes to a running count which represents the total decrements needed at each position.
  • Utilize a StringBuilder named output to construct the returning number as a string.
  • Iteratively construct the output leveraging the following logic:
    • If the current character is 'I', increment the highest marker, append it to output, and adjust tempMax.
    • If the current character is 'D', calculate the number using highest and the respective value from decrementSequence, then append this number to output and update tempMax.

This approach efficiently computes the smallest number in linear time relative to the length of input patterns, ensuring correctness by dynamically adjusting to the constraints provided by each character in the pattern. This balances between increments and calculated sequences of decrements, resulting in the desired smallest lexicographical order of numbers.

python
class Solution:
    def minimumNumber(self, seq: str) -> str:
        len_seq = len(seq)
        highest_num = current_high = intermediary = 0

        # Array to store spans of descending sequences
        desc_spans = [0] * (len_seq + 2)

        # Determine the descending sequence spans in given sequence
        for index in reversed(range(len_seq + 1)):
            if index < len_seq and seq[index] == 'D':
                # Increment the current span for 'D'
                desc_spans[index] = desc_spans[index + 1] + 1
        constructed_result = ""

        # Forming the final string based on sequence characters
        for idx in range(len_seq + 1):
            if idx < len_seq and seq[idx] == 'I':
                # Determine the number to append for 'I'
                highest_num += 1
                constructed_result += str(highest_num)

                # Identify the highest number so far
                highest_num = max(highest_num, current_high)

                # Restart counting the max from zero for upcoming 'I'
                current_high = 0

            else:
                # Determine the number to append for 'D'
                intermediary = 1 + highest_num + desc_spans[idx]
                constructed_result += str(intermediary)

                # Update the current highest number in descending stretches
                current_high = max(current_high, intermediary)

        return constructed_result

The given solution focuses on constructing the smallest possible number from a sequence pattern described by 'D' and 'I' characters, where 'D' stands for a descending order of numbers and 'I' for an ascending order. This Python3 class, Solution, defines a method minimumNumber(seq) that takes a string seq to process this pattern.

  • Initially, variables to hold sequence length, the highest number needed, and other placeholders for computation are set up.
  • An array, desc_spans, serves to hold the length of contiguous 'D' sequences, which helps in figuring out how much to increment numbers during 'D' sequences.
  • Loop through the sequence in reverse to populate the desc_spans based on whether the current character is 'D'.
  • A second loop processes each character in the sequence. Depending on whether it encounters an 'I' or 'D':
    • For 'I', increment highest_num to place the next higher number and append it to the result string.
    • For 'D', calculate the number based on highest_num and the descending span so far, then append this to the result.
  • This algorithm cleverly keeps track of increments needed during 'D' spans and adjusts the sequence to assemble the smallest number that respects the 'D' and 'I' patterns.
  • The method finally returns the constructed result as a string, showcasing efficient planning and execution for handling sequences.

This approach ensures space-efficient and time-effective calculation by performing operations in linear passes and using integers and basic list manipulations.

Comments

No comments yet.