C++ | Smallest string with given value | 0ms | Explained with textual images | Using Greedy approach
365

Problem Statement : https://leetcode.com/problems/smallest-string-with-a-given-numeric-value/

Note: Go check down to view similar kind of problem and approach.

Approach:

  • An ideal approach to this kind of problem is to build the solution from the end [Since in lexicographical order all the highest characters need to be at the end of the string].
  • Check the value of k and update the answer accordingly.

If you are not interested in the algorithm, please jump to the code.


Algorithm:

  1. As discussed above, we need to build the answer from the end.
  2. So, we push all the higher characters (i.e.,) 'z' from the end. But here comes a problem that if we push all the highest characters first then there might not be characters available to append in the start of the string.
    Ex: n = 2, k =26, Here if we append 'z' to the end of the string then ans = "z" and k = 0 but we need a string of length 2 which is not possible in this case.
  3. So to avoid the above case, we shall first place the minimal characters 'a' at all positions of the string. So that we can update the final string later corresponding to the k vlaue.
  4. Iterater over the string from the end. If there is a k value a minimum of 25 then replace the current character with z or otherwise replace it with remaining k vlaue.
    Note: Here, after append all a's to the string, we use 25 form k to get 'z' instead of 26 because string is already updated with a and the remaining balance to update to 'z' is 25 only.

Step wise iteration of algorithm:
Given string n = 5, k = 73.

  1. Append n number of a's to the string: ans = "aaaaa".
        -------------------------------
ans  =  |  a  |  a  |  a  |  a  |  a  |
        -------------------------------
  1. Update the k value, k -= n, k = 73-5 = 68.
  2. Iterating from the end of the string. Since k >= 25 update the current character to 'z' and k becomes 43 (68-25). ans = "aaaaz".
        -------------------------------               -------------------------------
ans  =  |  a  |  a  |  a  |  a  |  a  |      -->      |  a  |  a  |  a  |  a  |  z  |
        -------------------------------               -------------------------------
                                   ^                                             ^
  1. Since k >= 25 update the current character to 'z' and k becomes 18 (43-25). ans = "aaazz".
        -------------------------------               -------------------------------
ans  =  |  a  |  a  |  a  |  a  |  z  |      -->      |  a  |  a  |  a  |  z  |  z  |
        -------------------------------               -------------------------------
                             ^                                             ^
  1. Now, since k < 25, we will update the current character with correspoding value to k. Current character is curr = 'a' + k = 'a' + 18 = 's' (19).
        -------------------------------               -------------------------------
ans  =  |  a  |  a  |  a  |  z  |  z  |      -->      |  a  |  a  |  s  |  z  |  z  |
        -------------------------------               -------------------------------
                       ^                                             ^
  1. Finally the answer is ans = "aaszz".

Approach: Using Greedy approach
Type - 1:

class Solution {
public:
    string getSmallestString(int n, int k) {
        string ans = string(n, 'a');
        k -= n;
        for(int curr = n-1; curr >= 0; --curr) {
            if(k >= 25) ans[curr] = 'z';
            else ans[curr] += k;
            k -= min(k, 25);
        }
        return ans;
    }
};

This code work fine, but there is no need to travel the entire string in all cases. This can be optimized as - We will travel the string only if k value is available. This can be done in 2 ways.

for(int curr = n-1; curr >= 0; --curr) {
	if(k >= 25) ans[curr] = 'z';
	else ans[curr] += k;
	k -= min(k, 25);
	if(k == 0) break;
}

(or) we can add the k value to the character directly instead of assigning with 'z'.

while(k > 0) {
	ans[--n] += min(25, k);
	k -= min(25, k);
}

Now the final code looks like -

class Solution {
public:
    string getSmallestString(int n, int k) {
        string ans = string(n, 'a');
        k -= n;
        while(k > 0) {
            ans[--n] += min(25, k);
            k -= min(25, k);
        }
        return ans;
    }
};

Similar Problem:
https://leetcode.com/problems/maximum-69-number/ [Easy]
https://leetcode.com/problems/create-maximum-number/ [Hard]


Upvote if you like.
Thank you.

Comments (0)