给定一个数字字符串“ 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的长度。
在继续解决此问题时,我们应确保输出字符串在其高权重位置包含最小值。因此我们通过使用堆栈来确保
- 如果k> = n,则返回0。如果k = 0,则返回num。
- 创建一个堆栈并遍历num字符串,如果该值大于堆栈的顶部元素,则将该值压入该位置。
- 遍历num字符串,如果该位置的整数值小于堆栈顶部,我们将弹出堆栈并递减k,直到达到堆栈顶部小于我们正在查看的值的条件为止(而k> 0时)(通过这种方式,我们可以确保结果的最高有效位置填充有最小值)。
- 如果k仍然大于0,我们将弹出堆栈,直到k变为0。
- 将堆栈中的元素追加到结果字符串。
- 从结果字符串删除前导零。
下面是上述方法的实现:
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)