Skip to content
Related Articles

Related Articles

Improve Article

Build Lowest Number by Removing n digits from a given number

  • Difficulty Level : Hard
  • Last Updated : 28 Jun, 2021

Given a string ‘str’ of digits and an integer ‘n’, build the lowest possible number by removing ‘n’ digits from the string and not changing the order of input digits.
Examples: 

Input: str = "4325043", n = 3
Output: "2043"

Input: str = "765028321", n = 5
Output: "0221"

Input: str = "121198", n = 2
Output: "1118"

The idea is based on the fact that a character among first (n+1) characters must be there in resultant number. So we pick the smallest of first (n+1) digits and put it in result, and recur for the remaining characters. Below is complete algorithm.  

Initialize result as empty string
     res = ""
buildLowestNumber(str, n, res)
1) If n == 0, then there is nothing to remove.
   Append the whole 'str' to 'res' and return

2) Let 'len' be length of 'str'. If 'len' is smaller or equal 
   to n, then everything can be removed
   Append nothing to 'res' and return

3) Find the smallest character among first (n+1) characters
   of 'str'.  Let the index of smallest character be minIndex.
   Append 'str[minIndex]' to 'res' and recur for substring after
   minIndex and for n = n-minIndex

     buildLowestNumber(str[minIndex+1..len-1], n-minIndex).

Below is the implementation of the above algorithm:

C++14




// C++ program to build the smallest number by removing n
// digits from a given number
#include <iostream>
using namespace std;
  
// A recursive function that removes 'n' characters from
// 'str' to store the smallest possible number in 'res'
void buildLowestNumberRec(string str, int n, string& res)
{
    // If there are 0 characters to remove from str,
    // append everything to result
    if (n == 0) {
        res.append(str);
        return;
    }
  
    int len = str.length();
  
    // If there are more characters to remove than string
    // length, then append nothing to result
    if (len <= n)
        return;
  
    // Find the smallest character among first (n+1)
    // characters of str.
    int minIndex = 0;
    for (int i = 1; i <= n; i++)
        if (str[i] < str[minIndex])
            minIndex = i;
  
    // Append the smallest character to result
    res.push_back(str[minIndex]);
  
    // substring starting from minIndex+1 to str.length()
    // - 1.
    string new_str
        = str.substr(minIndex + 1, len - minIndex);
  
    // Recur for the above substring and n equals to
    // n-minIndex
    buildLowestNumberRec(new_str, n - minIndex, res);
}
  
// A wrapper over buildLowestNumberRec()
string buildLowestNumber(string str, int n)
{
    string res = "";
  
    // Note that result is passed by reference
    buildLowestNumberRec(str, n, res);
    
    // Remove all the leading zeroes
    string ans = "";
    int flag = 0;
    for (int i = 0; i < res.length(); i++) 
    {
        if (res[i] != '0' || flag == 1) 
        {
            flag = 1;
            ans += res[i];
        }
    }
  
    if (ans.length() == 0)
        return "0";
    else
        return ans;
  
     
}
  
// Driver program to test above function
int main()
{
    string str = "121198";
    int n = 2;
    cout << buildLowestNumber(str, n);
    return 0;
}

Java




// Java program to build the smallest number
// by removing n digits from a given number
class GFG {
    static String res = "";
  
    // A recursive function that removes
    // 'n' characters from 'str' to store
    // the smallest possible number in 'res'
    static void buildLowestNumberRec(String str, int n)
    {
  
        // If there are 0 characters to remove from str,
        // append everything to result
        if (n == 0) {
            res += str;
            return;
        }
  
        int len = str.length();
  
        // If there are more characters to
        // remove than string length,
        // then append nothing to result
        if (len <= n)
            return;
  
        // Find the smallest character among
        // first (n+1) characters of str.
        int minIndex = 0;
        for (int i = 1; i <= n; i++)
            if (str.charAt(i) < str.charAt(minIndex))
                minIndex = i;
  
        // Append the smallest character to result
        res += str.charAt(minIndex);
  
        // substring starting from
        // minIndex+1 to str.length() - 1.
        String new_str = str.substring(minIndex + 1);
  
        // Recur for the above substring
        // and n equals to n-minIndex
        buildLowestNumberRec(new_str, n - minIndex);
    }
  
    static String lowestNumber(String str, int n)
    {
        buildLowestNumberRec(str, n);
        String ans = "";
        int flag = 0;
        for (int i = 0; i < res.length(); i++) {
            if (res.charAt(i) != '0' || flag == 1) {
                ans += res.charAt(i);
            }
        }
  
        if (ans.length() == 0)
            return "0";
        else
            return ans;
    }
  
    // Driver Code
    public static void main(String[] args)
    {
        String str = "390028";
        int n = 2;
        String ans = lowestNumber(str, n);
  
        System.out.println(ans);
    }
}

C#




// C# program to build the smallest number
// by removing n digits from a given number
using System;
  
class GFG {
    static String res = "";
  
    // A recursive function that removes
    // 'n' characters from 'str' to store
    // the smallest possible number in 'res'
    static void buildLowestNumberRec(String str, int n)
    {
  
        // If there are 0 characters to remove from str,
        // append everything to result
        if (n == 0) {
            res += str;
            return;
        }
  
        int len = str.Length;
  
        // If there are more characters to
        // remove than string length,
        // then append nothing to result
        if (len <= n)
            return;
  
        // Find the smallest character among
        // first (n+1) characters of str.
        int minIndex = 0;
        for (int i = 1; i <= n; i++)
            if (str[i] < str[minIndex])
                minIndex = i;
  
        // Append the smallest character to result
        res += str[minIndex];
  
        // substring starting from
        // minIndex+1 to str.length() - 1.
        String new_str = str.Substring(minIndex + 1);
  
        // Recur for the above substring
        // and n equals to n-minIndex
        buildLowestNumberRec(new_str, n - minIndex);
    }
    
    static String lowestNumber(String str, int n)
    {
         buildLowestNumberRec(str,n);
         String ans = "";
         int flag = 0;
         for(int i = 0;i<res.Length;i++)
         {
              if(res[i] != '0' || flag == 1)
              {
                   ans += res[i];
              }
         }
        
         if(ans.Length == 0)
           return "0";
         else 
           return ans;
    }
  
    // Driver Code
    public static void Main(String[] args)
    {
        String str = "390028";
        int n = 2;
        String ans = lowestNumber(str, n);
        
        Console.Write(ans);
    }
}
  
// This code is contributed by
// Rajnis09

Output: 

1118

Below is an optimized code in C++ contributed by Gaurav Mamgain  



C++14




// C++ program to build the smallest number by removing
// n digits from a given number
#include <bits/stdc++.h>
using namespace std;
  
void insertInNonDecOrder(deque<char>& dq, char ch)
{
  
    // If container is empty , insert the current digit
    if (dq.empty())
        dq.push_back(ch);
  
    else {
        char temp = dq.back();
  
        // Keep removing digits larger than current digit
        // from the back side of deque
        while (temp > ch && !dq.empty()) {
            dq.pop_back();
            if (!dq.empty())
                temp = dq.back();
        }
  
        // Insert the current digit
        dq.push_back(ch);
    }
    return;
}
  
string buildLowestNumber(string str, int n)
{
    int len = str.length();
  
    // Deleting n digits means we need to print k digits
    int k = len - n;
  
    deque<char> dq;
    string res = "";
  
    // Leaving rightmost k-1 digits we need to choose
    // minimum digit from rest of the string and print it
    int i;
    for (i = 0; i <= len - k; i++)
  
        // Insert new digit from the back side in
        // appropriate position and/ keep removing
        // digits larger than current digit
        insertInNonDecOrder(dq, str[i]);
  
    // Now the minimum digit is at front of deque
    while (i < len) {
  
        // keep the minimum digit in output string
        res += dq.front();
  
        // remove minimum digit
        dq.pop_front();
  
        // Again insert new digit from the back
        // side in appropriate position and keep
        // removing digits larger than current digit
        insertInNonDecOrder(dq, str[i]);
        i++;
    }
  
    // Now only one element will be there in the deque
    res += dq.front();
    dq.pop_front();
    return res;
}
  
string lowestNumber(string str, int n)
{
    string res = buildLowestNumber(str, n);
      
    // Remove all the leading zeroes
    string ans = "";
    int flag = 0;
    for (int i = 0; i < res.length(); i++) {
        if (res[i] != '0' || flag == 1) {
            flag = 1;
            ans += res[i];
        }
    }
  
    if (ans.length() == 0)
        return "0";
    else
        return ans;
}
  
// Driver program to test above function
int main()
{
    string str = "765028321";
    int n = 5;
    cout <<lowestNumber(str, n) << endl;
    return 0;
}
// This code is contributed by Gaurav Mamgain
Output
221

Output:

0221

Time Complexity: O(N) 
Space Complexity: O(N)

Approach:2

Let’s suppose the length of the given string num be n.so the result string will contain the length of n-k.

As we proceed to solve this problem we should make sure that the output string contains minimum values at their high weightage positions. so we ensure that by using a stack.

  1. Return 0 if k >=n. and return num if k=0.
  2. Create a stack and iterate through num string and push the value at that position if it is greater than the top element of the stack.
  3. Iterate through the num string and if the integer value at that position is less than the top of the stack we will pop the stack and decrement k until we reach the condition where the top of the stack is less than the value we are looking at(while k>0) (by this we are making sure that most significant positions of the result are filled with minimum values).
  4. If the k is still greater than 0 we will pop stack until k becomes 0.
  5. Append the elements in the stack to the result string.
  6. Delete leading zeroes from the result string.

Below is the implementation of the above approach:

Java




// Java program for the above approach
import java.io.*;
import java.util.*;
  
class GFG {
  
    public static String removeKdigits(String num, int k)
    {
        StringBuilder result = new StringBuilder();
          
        // We have to delete all digits
        if (k >= num.length()) {
            return "0";
        }
        // Nothing to delete
        if (k == 0) {
            return num;
        }
        Stack<Character> s = new Stack<Character>();
  
        for (int i = 0; i < num.length(); i++) {
            char c = num.charAt(i);
            
            // Removing all digits in stack that are greater
            // tha this digit(since they have higher
            // weightage)
            while (!s.isEmpty() && k > 0 && s.peek() > c) {
                s.pop();
                k--;
            }
            // ignore pushing 0
            if (!s.isEmpty() || c != '0')
                s.push(c);
        }
        
        // If our k isnt 0 yet then we keep poping out the
        // stack until k becomes 0
        while (!s.isEmpty() && k > 0) {
            k--;
            s.pop();
        }
        if (s.isEmpty())
            return "0";
        while (!s.isEmpty()) {
            result.append(s.pop());
        }
        String str = result.reverse().toString();
  
        return str;
    }
  
    // Driver Code
    public static void main(String[] args)
    {
        String s = "765028321";
        int k = 5;
        System.out.println(removeKdigits(s, 5));
    }
}
// this code is contributed by gireeshgudaparthi

C++




// C++ program for the above approach
  
#include <bits/stdc++.h>
using namespace std;
  
string removeKdigits(string num, int k)
{
    int n = num.size();
    stack<char> mystack;
    // Store the final string in stack
    for (char c : num) {
        while (!mystack.empty() && k > 0
               && mystack.top() > c) {
            mystack.pop();
            k -= 1;
        }
  
        if (!mystack.empty() || c != '0')
            mystack.push(c);
    }
  
    // Now remove the largest values from the top of the
    // stack
    while (!mystack.empty() && k--)
        mystack.pop();
    if (mystack.empty())
        return "0";
  
    // Now retrieve the number from stack into a string
    // (reusing num)
    while (!mystack.empty()) {
        num[n - 1] = mystack.top();
        mystack.pop();
        n -= 1;
    }
    return num.substr(n);
}
  
int main()
{
    string str = "765028321";
    int k = 5;
    cout << removeKdigits(str, k);
    return 0;
}
Output
221

Time complexity: O(N)
Space complexity: O(N)

This article is contributed by Pallav Gurha. Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.

Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with experts, please refer DSA Live Classes for Working Professionals and Competitive Programming Live for Students.




My Personal Notes arrow_drop_up