给一个正整数 NUM1
,计算出新正整数 NUM2
,NUM2
为 NUM1
中移除 N
位数字后的结果,需要使得 NUM2
的值最小。
NUM1
,NUM1
长度小于 32。NUM1
长度。输出一个数字字符串,记录最小值 NUM2
。
输入:
2615371
4
输出:
131
为了得到最小的 NUM2
,我们需要从 NUM1
中移除 N
位数字。移除数字的策略是:
NUM1
,尽可能移除较大的数字,以使剩余的数字最小。读取输入:
NUM1
。N
。初始化栈:
stack
,用于存储最终的 NUM2
。遍历 NUM1
:
NUM1
中的每个数字 digit
:
stack
不为空且 stack
的栈顶元素大于 digit
,并且 N
大于 0:
stack
的栈顶元素。N
减 1。digit
压入 stack
。处理剩余的 N
:
N
仍然大于 0,从 stack
的末尾移除 N
个元素。构建 NUM2
:
stack
中的元素拼接成字符串,得到 NUM2
。输出结果:
NUM2
。NUM1 = 2615371
N = 4
131
解释:
2615371
:
2
-> 压入 stack
,stack = [2]
6
-> 压入 stack
,stack = [2, 6]
1
-> stack
的栈顶元素 6
大于 1
,弹出 6
,N = 3
,stack = [2]
5
-> 压入 stack
,stack = [2, 5]
3
-> stack
的栈顶元素 5
大于 3
,弹出 5
,N = 2
,stack = [2]
7
-> 压入 stack
,stack = [2, 7]
1
-> stack
的栈顶元素 7
大于 1
,弹出 7
,N = 1
,stack = [2]
N
:
stack
的末尾移除 1
个元素,stack = [1]
NUM2
:
stack
中的元素拼接成字符串,得到 131
通过上述步骤,我们可以高效地求出最小的 NUM2
。这种方法的时间复杂度为 O(n)
,其中 n
是 NUM1
的长度。
以下是带有详细中文注释和讲解的 JavaScript 代码:
/* JavaScript Node ACM模式 控制台输入获取 */
const readline = require("readline");
// 创建 readline 接口,用于从控制台读取输入
const rl = readline.createInterface({
input: process.stdin, // 输入流为标准输入
output: process.stdout, // 输出流为标准输出
});
// 存储输入行的数组
const lines = [];
// 监听 'line' 事件,每次读取一行输入
rl.on("line", (line) => {
// 将输入行添加到 lines 数组中
lines.push(line);
// 当读取到两行输入时,开始处理
if (lines.length === 2) {
// 将第一行输入转换为数字数组
const arr = lines[0].split("").map((ele) => parseInt(ele));
// 获取第二行输入,表示需要移除的字符数量
const removeCount = lines[1];
// 调用 getMinValue 方法并输出结果
console.log(getMinValue(arr, removeCount));
}
});
/**
* 获取移除指定数量字符后的最小数字字符串
* @param {number[]} arr 原始数字数组
* @param {number} removeCount 需要移除的字符数量
* @returns {string} 移除指定数量字符后的最小数字字符串
*/
function getMinValue(arr, removeCount) {
// 如果移除的字符数量等于数组长度,直接返回 "0"
if (arr.length === removeCount) return "0";
// 计算需要保留的字符数量
let remainCount = arr.length - removeCount;
// 使用数组模拟栈结构
let stack = [];
for (let i = 0; i < arr.length; i++) {
// 当栈不为空、仍有字符需要移除、且栈顶字符大于当前字符时
while (
stack.length > 0 &&
removeCount > 0 &&
stack[stack.length - 1] > arr[i]
) {
// 移除栈顶字符(保证结果最小)
stack.pop();
// 减少需要移除的字符数量
removeCount--;
}
// 将当前字符压入栈中
stack.push(arr[i]);
}
// 如果栈中字符数量超过需要保留的数量,移除多余的字符
while (stack.length > remainCount) {
stack.pop();
}
// 移除前导零(如果存在且栈中字符数量大于 1)
while (stack[0] === 0 && stack.length !== 1) {
stack.shift();
}
// 将栈中的字符拼接成字符串并返回
return stack.join("");
}
readline
模块:
readline
模块从控制台读取输入。rl.on('line', callback)
监听每一行的输入。lines
数组中。getMinValue
方法:arr
中移除 removeCount
个字符,使得剩下的字符组成的数字最小。removeCount
等于 arr
的长度,直接返回 "0"
。remainCount = arr.length - removeCount
。arr
的每个字符:
remainCount
,移除多余的字符。0
且栈中字符数量大于 1,移除前导零。arr
的长度。1432219
3
1
:压入栈,栈为 [1]
。4
:压入栈,栈为 [1, 4]
。3
:发现栈顶 4
大于 3
,移除 4
,栈为 [1, 3]
。2
:发现栈顶 3
大于 2
,移除 3
,栈为 [1, 2]
。2
:压入栈,栈为 [1, 2, 2]
。1
:发现栈顶 2
大于 1
,移除 2
,栈为 [1, 2, 1]
。9
:压入栈,栈为 [1, 2, 1, 9]
。"1219"
。1219
如果有其他问题,欢迎继续提问!
以下是带有详细中文注释和讲解的代码:
import java.util.LinkedList;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// 创建 Scanner 对象用于读取输入
Scanner sc = new Scanner(System.in);
// 读取第一行输入,表示原始数字字符串
String num1 = sc.nextLine();
// 读取第二行输入,表示需要移除的字符数量
int count = Integer.parseInt(sc.nextLine());
// 调用 getResult 方法并输出结果
System.out.println(getResult(num1, count));
}
/**
* 获取移除指定数量字符后的最小数字字符串
* @param num1 原始数字字符串
* @param removeCount 需要移除的字符数量
* @return 移除指定数量字符后的最小数字字符串
*/
private static String getResult(String num1, int removeCount) {
// 如果移除的字符数量等于字符串长度,直接返回 "0"
if (num1.length() == removeCount) return "0";
// 计算需要保留的字符数量
int remainCount = num1.length() - removeCount;
// 使用 LinkedList 模拟栈结构
LinkedList<Character> stack = new LinkedList<>();
for (int i = 0; i < num1.length(); i++) {
// 当栈不为空、仍有字符需要移除、且栈顶字符大于当前字符时
while (stack.size() > 0 && removeCount > 0 && stack.getLast() > num1.charAt(i)) {
// 移除栈顶字符(保证结果最小)
stack.removeLast();
// 减少需要移除的字符数量
removeCount--;
}
// 将当前字符压入栈中
stack.add(num1.charAt(i));
}
// 如果栈中字符数量超过需要保留的数量,移除多余的字符
while (stack.size() > remainCount) {
stack.removeLast();
}
// 移除前导零(如果存在且栈中字符数量大于 1)
while (stack.getFirst() == '0' && stack.size() != 1) {
stack.removeFirst();
}
// 将栈中的字符拼接成最终结果
StringBuilder sb = new StringBuilder();
for (Character c : stack) sb.append(c);
return sb.toString();
}
}
main
:Scanner
读取两行输入:
num1
。count
。getResult
方法:
num1
和 count
作为参数传递给 getResult
方法,获取结果并输出。getResult
方法:num1
中移除 removeCount
个字符,使得剩下的字符串表示的数字最小。removeCount
等于 num1
的长度,直接返回 "0"
。remainCount = num1.length() - removeCount
。num1
的每个字符:
remainCount
,移除多余的字符。'0'
且栈中字符数量大于 1,移除前导零。num1
的长度。1432219
3
'1'
:压入栈,栈为 ['1']
。'4'
:压入栈,栈为 ['1', '4']
。'3'
:发现栈顶 '4'
大于 '3'
,移除 '4'
,栈为 ['1', '3']
。'2'
:发现栈顶 '3'
大于 '2'
,移除 '3'
,栈为 ['1', '2']
。'2'
:压入栈,栈为 ['1', '2', '2']
。'1'
:发现栈顶 '2'
大于 '1'
,移除 '2'
,栈为 ['1', '2', '1']
。'9'
:压入栈,栈为 ['1', '2', '1', '9']
。"1219"
。1219
如果有其他问题,欢迎继续提问!
以下是带有详细中文注释和讲解的 Python 代码:
# 输入获取
num1 = input() # 读取第一行输入,表示原始数字字符串
removeCount = int(input()) # 读取第二行输入,表示需要移除的字符数量
# 算法入口
def getResult(num1, removeCount):
# 如果移除的字符数量等于字符串长度,直接返回 "0"
if len(num1) == removeCount:
return "0"
# 计算需要保留的字符数量
remainCount = len(num1) - removeCount
# 使用列表模拟栈结构
stack = []
for i in range(len(num1)):
# 当栈不为空、仍有字符需要移除、且栈顶字符大于当前字符时
while len(stack) > 0 and removeCount > 0 and stack[-1] > num1[i]:
# 移除栈顶字符(保证结果最小)
stack.pop()
# 减少需要移除的字符数量
removeCount -= 1
# 将当前字符压入栈中
stack.append(num1[i])
# 如果栈中字符数量超过需要保留的数量,移除多余的字符
while len(stack) > remainCount:
stack.pop()
# 移除前导零(如果存在且栈中字符数量大于 1)
while stack[0] == '0' and len(stack) != 1:
stack.pop(0)
# 将栈中的字符拼接成字符串并返回
return "".join(stack)
# 算法调用
print(getResult(num1, removeCount))
input()
函数:
input()
函数从控制台读取输入。num1
。removeCount
。getResult
方法:num1
中移除 removeCount
个字符,使得剩下的字符串表示的数字最小。removeCount
等于 num1
的长度,直接返回 "0"
。remainCount = len(num1) - removeCount
。num1
的每个字符:
remainCount
,移除多余的字符。'0'
且栈中字符数量大于 1,移除前导零。num1
的长度。1432219
3
'1'
:压入栈,栈为 ['1']
。'4'
:压入栈,栈为 ['1', '4']
。'3'
:发现栈顶 '4'
大于 '3'
,移除 '4'
,栈为 ['1', '3']
。'2'
:发现栈顶 '3'
大于 '2'
,移除 '3'
,栈为 ['1', '2']
。'2'
:压入栈,栈为 ['1', '2', '2']
。'1'
:发现栈顶 '2'
大于 '1'
,移除 '2'
,栈为 ['1', '2', '1']
。'9'
:压入栈,栈为 ['1', '2', '1', '9']
。"1219"
。1219
如果有其他问题,欢迎继续提问!
以下是 C++ 和 C语言 版本的代码实现,并附带详细的中文注释和讲解。
#include
#include
#include
using namespace std;
// 算法入口
string getResult(string num1, int removeCount) {
// 如果移除的字符数量等于字符串长度,直接返回 "0"
if (num1.length() == removeCount) {
return "0";
}
// 计算需要保留的字符数量
int remainCount = num1.length() - removeCount;
// 使用 vector 模拟栈结构
vector<char> stack;
for (int i = 0; i < num1.length(); i++) {
// 当栈不为空、仍有字符需要移除、且栈顶字符大于当前字符时
while (!stack.empty() && removeCount > 0 && stack.back() > num1[i]) {
// 移除栈顶字符(保证结果最小)
stack.pop_back();
// 减少需要移除的字符数量
removeCount--;
}
// 将当前字符压入栈中
stack.push_back(num1[i]);
}
// 如果栈中字符数量超过需要保留的数量,移除多余的字符
while (stack.size() > remainCount) {
stack.pop_back();
}
// 移除前导零(如果存在且栈中字符数量大于 1)
while (stack.size() > 1 && stack[0] == '0') {
stack.erase(stack.begin());
}
// 将栈中的字符拼接成字符串并返回
string result(stack.begin(), stack.end());
return result;
}
int main() {
// 输入获取
string num1;
int removeCount;
cin >> num1 >> removeCount;
// 算法调用
cout << getResult(num1, removeCount) << endl;
return 0;
}
输入获取:
cin
从控制台读取输入。num1
是原始数字字符串。removeCount
是需要移除的字符数量。getResult
方法:
num1
中移除 removeCount
个字符,使得剩下的字符串表示的数字最小。vector
模拟栈结构。num1
的每个字符,通过贪心算法移除比当前字符大的栈顶字符。核心思想:
num1
的长度。示例:
1432219
3
1219
#include
#include
#include
// 算法入口
char* getResult(char* num1, int removeCount) {
int len = strlen(num1);
// 如果移除的字符数量等于字符串长度,直接返回 "0"
if (len == removeCount) {
char* result = (char*)malloc(2 * sizeof(char));
result[0] = '0';
result[1] = '\0';
return result;
}
// 计算需要保留的字符数量
int remainCount = len - removeCount;
// 使用数组模拟栈结构
char* stack = (char*)malloc((len + 1) * sizeof(char));
int top = -1; // 栈顶指针
for (int i = 0; i < len; i++) {
// 当栈不为空、仍有字符需要移除、且栈顶字符大于当前字符时
while (top >= 0 && removeCount > 0 && stack[top] > num1[i]) {
// 移除栈顶字符(保证结果最小)
top--;
// 减少需要移除的字符数量
removeCount--;
}
// 将当前字符压入栈中
stack[++top] = num1[i];
}
// 如果栈中字符数量超过需要保留的数量,移除多余的字符
while (top + 1 > remainCount) {
top--;
}
// 移除前导零(如果存在且栈中字符数量大于 1)
int start = 0;
while (start <= top && stack[start] == '0') {
start++;
}
// 如果所有字符都被移除,返回 "0"
if (start > top) {
char* result = (char*)malloc(2 * sizeof(char));
result[0] = '0';
result[1] = '\0';
free(stack);
return result;
}
// 将栈中的字符拼接成字符串并返回
char* result = (char*)malloc((top - start + 2) * sizeof(char));
int index = 0;
for (int i = start; i <= top; i++) {
result[index++] = stack[i];
}
result[index] = '\0';
free(stack);
return result;
}
int main() {
// 输入获取
char num1[1000];
int removeCount;
scanf("%s", num1);
scanf("%d", &removeCount);
// 算法调用
char* result = getResult(num1, removeCount);
printf("%s\n", result);
// 释放动态分配的内存
free(result);
return 0;
}
输入获取:
scanf
从控制台读取输入。num1
是原始数字字符串。removeCount
是需要移除的字符数量。getResult
方法:
num1
中移除 removeCount
个字符,使得剩下的字符串表示的数字最小。num1
的每个字符,通过贪心算法移除比当前字符大的栈顶字符。核心思想:
num1
的长度。示例:
1432219
3
1219
内存管理:
malloc
动态分配内存,并在使用完毕后通过 free
释放内存。vector
模拟栈,代码更简洁。如果有其他问题,欢迎继续提问!