📜  通过从给定号码中删除n位数字来建立最低号码

📅  最后修改于: 2021-04-23 17:07:57             🧑  作者: Mango

给定一个数字字符串“ str”和一个整数“ n”,通过从字符串删除“ n”个数字而不更改输入数字的顺序来构建尽可能小的数字。
例子:

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

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

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

这个想法基于这样一个事实,即前(n + 1)个字符中的一个字符必须在结果数中存在。因此,我们选择前(n + 1)个数字中的最小数字并将其放入结果中,然后对其余字符递归处理。下面是完整的算法。

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).

下面是上述算法的实现:

C++14
// C++ program to build the smallest number by removing n
// digits from a given number
#include 
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


C++14
// C++ program to build the smallest number by removing
// n digits from a given number
#include 
using namespace std;
 
void insertInNonDecOrder(deque& 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 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 <


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 s = new Stack();
 
        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


输出:

1118

以下是由Gaurav Mamgain提供的C++优化代码

C++ 14

// C++ program to build the smallest number by removing
// n digits from a given number
#include 
using namespace std;
 
void insertInNonDecOrder(deque& 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 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 <
输出
221

输出:

0221

时间复杂度: O(N)
空间复杂度: O(N)

方法:2

假设给定字符串num的长度为n。因此结果字符串将包含nk的长度。

在继续解决此问题时,我们应确保输出字符串在其高权重位置包含最小值。因此我们通过使用堆栈来确保

  1. 如果k> = n,则返回0。如果k = 0,则返回num。
  2. 创建一个堆栈并遍历num字符串,如果该值大于堆栈的顶部元素,则将该值压入该位置。
  3. 遍历num字符串,如果该位置的整数值小于堆栈顶部,我们将弹出堆栈并递减k,直到达到堆栈顶部小于我们正在查看的值的条件为止(而k> 0时)(通过这种方式,我们可以确保结果的最高有效位置填充有最小值)。
  4. 如果k仍然大于0,我们将弹出堆栈,直到k变为0。
  5. 将堆栈中的元素追加到结果字符串。
  6. 从结果字符串删除前导零。

下面是上述方法的实现:

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 s = new Stack();
 
        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
输出
221

时间复杂度: O(N)
空间复杂度: O(N)