题目
设有一个正整数由n位数构成,删除其中的任意k位数后所得到的正整数最大
输入格式
输入要求:输入的第1行为该正整数,第2行为需要删除的位数k
输出格式
输出要求:输出删除k位数之后的最大的正整数。
输入样例
196857 2
输出样例
9857
解题思路
思路一 [ 贪心 ]
1. 每次从高位向低位数比较 [ **从左向右比较** ]
- 若**高位数字小**,则删除高位数字
- 若**高位数字大**,则继续向后比较
2. 从高位向低位依次比较结束,未找到高位小于低位的数字,则**删除末尾数字**
- **解释:**比较序列**下标**是从 **0 **开始到 **num.size() - 2** 结束
🍖实例说明
2319274 从高位向低位数比较
K=1 时,2<3 ,删除2,得到 319274**
K=2 时,2<3 ,删除2,得到** 319274**
3>1 ,略过
1<9, 删除1,得到 39274
K=3 时, 2<3 ,删除2,得到** 319274**
3>1 ,略过
1<9 ,删除1,得到 **39274**
3<9 ,删除3,得到** 9274**
**
思路二 [ 动态规划 ]
分析:
1. 假设** str** 为长度为** n **的数字字符串
1. **S[i][j] **表示删除 **str[0...i-1] **中** j **个数字后的**最大字符数字**
1. 如果删除第** i **个数
- 则 **S[i][j] **等于删除前 **i-1 **个字符中的 **j-1 **位的最优解
- 即 **S[i][j]=S[i-1][j-1]**
4. 如果不删除第 **i **个数
- 则** S[i][j]** 等于删除前** i-1 **个字符中** j **位的最优解+str[i]
- 即 **S[i][j]=S[i-1][j]+str[i-1]**
5. 即 **S[i][j]=max(S[i-1][j-1],S[i-1][j]+str[i-1])**
5. 初始状态为当** j=0** 时,不删除任何位的数字,即 **S[i][j]=str[0...i-1]**
状态转移方程如下
时间复杂度:O( n×k )
空间复杂度:O( n×k )
优化:
1. 上述的转移方程** S[i][j]=max(S[i-1][j-1],S[i-1][j]+str[i-1])**
1. 可看出在**每次 i 循环**,**只与 i-1 相关**,因此只需要通过一个变量 **last **保存上一次的结果
1. 故状态转移方程可以简化为** S[j]=max(last,S[j]+str[i-1])**
解题代码
贪心代码
/***
* 参数解释:
* i变量 : for循环基础变量
* k变量 : 存储要删除的位数个数
* num数组 : 用于存放正整数数字
****/
#include<string>
using namespace std;
void Delete(string &num,int k) {
if (k > num.size())//排除异常输入
return;
while (k--) {
int i ;
for (i = 0; i < num.size() - 1; i++) { //依次从左向右检查
if (num[i] < num[i + 1]) { //高位数字小于低位数字
num.erase(num.begin()+i); //删除 i 下标,即高位数字
break;
}
}
if(i== num.size() - 1) //从左向右检查,高位数字均小于低位数字
num.erase(num.end()-1); //删除未位数字
}
if (!num.size()) //数组全删光,置零
num.push_back('0'); //🚩注意: num[0]='0' 赋值错误,原因不详
}
int main()
{
string num;
int k;
cin >> num >> k;
Delete(num, k);
cout << num << endl;
system("pause");
return 0;
}
动态规划代码
#include<string>
using namespace std;
// dynamic programming
// time complexity: O(n*k)
// space complexity: O(n*k)
string deleteKBits_2(string str,int k){
int tlen=str.length();
vector<vector<string> > nums(tlen+1,vector<string>(k+1));
string s1,s2;
for(int i=1;i<=tlen;i++){
for(int j=0;j<i && j<=k;j++){
if(j==0){
nums[i][j]=str.substr(0,i);
}
else{
s1=nums[i-1][j-1];
s2=nums[i-1][j]+str[i-1];
if(s1.compare(s2)<=0)
nums[i][j]=s2;
else
nums[i][j]=s1;
}
}
}
return nums[tlen][k];
}
// dynamic programming
// time complexity: O(n*k)
// space complexity: O(k)
string deleteKBits_3(string str,int k){
int tlen=str.length();
vector<string> nums(k+1);
string s1,s2,last;
for(int i=1;i<=tlen;i++){
for(int j=0;j<i && j<=k;j++){
if(j==0){
last=nums[j];
nums[j]=str.substr(0,i);
}
else{
// s1=last
s1=nums[j-1];
s2=nums[j]+str[i-1];
if(s1.compare(s2)<=0){
last=nums[j];
nums[j]=s2;
}
else{
last=nums[j];
nums[j]=s1;
}
}
}
}
return nums[k];
}
// dynamic programming
// time complexity: O(n*k)
// space complexity: O(k)
string deleteKBits_4(string str,int k){
int tlen=str.length();
vector<string> nums(k+1);
string tmp,s2,last;
for(int i=1;i<=tlen;i++){
for(int j=0;j<i && j<=k;j++){
if(j==0){
last=nums[j];
nums[j]=str.substr(0,i);
}
else{
// s1=last
// s1=nums[j-1];
s2=nums[j]+str[i-1];
if(last.compare(s2)<=0){
last=nums[j];
nums[j]=s2;
}
else{
tmp=nums[j];
nums[j]=last;
last=tmp;
}
}
}
}
return nums[k];
}
int main()
{
string str="2319274";
int k=3;
cout <<deleteKBits_2(str,k)<< endl;
cout <<deleteKBits_3(str,k)<< endl;
cout <<deleteKBits_4(str,k)<< endl;
system("pause");
return 0;
}