這道題可以使用貪心算法來解決,核心思路是盡量讓高位的數字盡可能小。當我們逐步刪除數字時,會優先刪除高位中相對較大的數字。具體做法是從左到右遍歷數字序列,當發現當前數字比它后面的數字大時,就刪除當前數字,直到刪除了S個數字或者遍歷完整個序列。如果遍歷完后刪除的數字個數還不夠S個,就從序列的末尾繼續刪除。
【算法思路】
- 輸入處理:使用
string
類型存儲高精度的正整數num
,并讀取要刪除的數字個數s
。
這道題為什么用字符串存儲而不是數組存儲?
①處理大整數的便利性:題目中明確提到輸入的是一個高精度的正整數,且不超過 250 位。普通的整數類型(如 int
、long long
)所能表示的數值范圍是有限的,無法存儲如此大的數字。字符串可以輕松地存儲任意長度的數字序列,它本質上是字符數組,每個字符對應數字的一位,不受數值范圍的限制。例如,對于一個 200 位的大整數,使用字符串可以直接將其按位存儲,不會出現溢出問題。
②操作的靈活性:在本題中,需要進行刪除數字的操作。字符串提供了方便的方法來刪除指定位置的字符,例如在 C++ 中可以使用 erase
函數。對于字符串 str
,可以使用 str.erase(i, 1)
輕松刪除第 i
個位置的字符。
//數組存儲
vector<int> num(n);
int k;
for(int i=0;i<n;i++){cin>>num[i];
}
cin>>k;//字符串存儲
string num;
int k;
cin>>num>>k;
- 刪數操作
- 進入一個循環,循環次數為
k
次。 - 在每次循環中,從左到右遍歷
num
,找到第一個滿足num[i] > num[i + 1]
的位置i
,然后刪除該位置的數字。 - 如果內層循環結束后
deleted
仍然為false
,說明在當前數字字符串中沒有找到遞減的位置,此時使用num.erase(num.length() - 1, 1)
刪除字符串的最后一個字符,并將k
減 1。
-
去除前導零:刪數操作完成后,可能會出現前導零的情況,因此需要去除前導零。
- 定義int類型的變量start變量初始化為0,用于記錄數字字符串中第一個非零字符的位置。
- 進入
while (start < num.length() && num[start] == '0')
循環,從字符串的開頭開始遍歷,只要沒有遍歷到字符串末尾且當前字符是0,就將start加1。 - 用三目運算符處理前導零并且給num賦予合適的值。
-
輸出結果:如果去除前導零后
num
為空,說明最終結果為 0,輸出0
;否則輸出num
。
【代碼示例】
#include<iostream>
#include<string>
using namespace std;int main(){string num;int k;cin>>num>>k;//進行k次刪除操作 while(k > 0){bool deleted=false;//標記是否找到遞減位置 for(int i=0;i < num.length()-1;++i){if(num[i] > num[i+1]){//找到第一個遞減的位置,刪除改位置的數字num.erase(i,1);deleted=true;k--;break;}}//如果沒找到遞減位置,刪除末尾字符 if(!deleted){num.erase(num.length() - 1,1); k--;}}//去除前導零int start=0;while (start < num.length() && num[start] == '0'){start++;}num = (start==num.length()) ? "0" : num.substr(start);cout<<num<<endl; return 0;
}
注意:
-
邊界處理:若序列完全遞增,刪除末尾數字
-
substr:是 std::string 類的一個成員函數,num.substr(start) 會返回從字符串 num 的第 start 個位置開始一直到字符串末尾的子字符串。