题目

设有一个正整数由n位数构成,删除其中的任意k位数后所得到的正整数最大

输入格式

输入要求:输入的第1行为该正整数,第2行为需要删除的位数k

输出格式

输出要求:输出删除k位数之后的最大的正整数。

输入样例

196857 2

输出样例

9857

解题思路

思路一 [ 贪心 ]

  1. 1. 每次从高位向低位数比较 [ **从左向右比较** ]
  2. - 若**高位数字小**,则删除高位数字
  3. - 若**高位数字大**,则继续向后比较
  4. 2. 从高位向低位依次比较结束,未找到高位小于低位的数字,则**删除末尾数字**
  5. - **解释:**比较序列**下标**是从 **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. 1. 假设** str** 为长度为** n **的数字字符串
  2. 1. **S[i][j] **表示删除 **str[0...i-1] **中** j **个数字后的**最大字符数字**
  3. 1. 如果删除第** i **个数
  4. - **S[i][j] **等于删除前 **i-1 **个字符中的 **j-1 **位的最优解
  5. - **S[i][j]=S[i-1][j-1]**
  6. 4. 如果不删除第 **i **个数
  7. - 则** S[i][j]** 等于删除前** i-1 **个字符中** j **位的最优解+str[i]
  8. - **S[i][j]=S[i-1][j]+str[i-1]**
  9. 5. **S[i][j]=max(S[i-1][j-1],S[i-1][j]+str[i-1])**
  10. 5. 初始状态为当** j=0** 时,不删除任何位的数字,即 **S[i][j]=str[0...i-1]**

状态转移方程如下

删除K位后使得数字最大 - 图1

时间复杂度:O( n×k )
空间复杂度:O( n×k )


优化:

  1. 1. 上述的转移方程** S[i][j]=max(S[i-1][j-1],S[i-1][j]+str[i-1])**
  2. 1. 可看出在**每次 i 循环**,**只与 i-1 相关**,因此只需要通过一个变量 **last **保存上一次的结果
  3. 1. 故状态转移方程可以简化为** S[j]=max(last,S[j]+str[i-1])**

时间复杂度:O( n×k )
空间复杂度:O( k )

解题代码

贪心代码

  1. /***
  2. * 参数解释:
  3. * i变量 : for循环基础变量
  4. * k变量 : 存储要删除的位数个数
  5. * num数组 : 用于存放正整数数字
  6. ****/
  7. #include<string>
  8. using namespace std;
  9. void Delete(string &num,int k) {
  10. if (k > num.size())//排除异常输入
  11. return;
  12. while (k--) {
  13. int i ;
  14. for (i = 0; i < num.size() - 1; i++) { //依次从左向右检查
  15. if (num[i] < num[i + 1]) { //高位数字小于低位数字
  16. num.erase(num.begin()+i); //删除 i 下标,即高位数字
  17. break;
  18. }
  19. }
  20. if(i== num.size() - 1) //从左向右检查,高位数字均小于低位数字
  21. num.erase(num.end()-1); //删除未位数字
  22. }
  23. if (!num.size()) //数组全删光,置零
  24. num.push_back('0'); //🚩注意: num[0]='0' 赋值错误,原因不详
  25. }
  26. int main()
  27. {
  28. string num;
  29. int k;
  30. cin >> num >> k;
  31. Delete(num, k);
  32. cout << num << endl;
  33. system("pause");
  34. return 0;
  35. }

动态规划代码

  1. #include<string>
  2. using namespace std;
  3. // dynamic programming
  4. // time complexity: O(n*k)
  5. // space complexity: O(n*k)
  6. string deleteKBits_2(string str,int k){
  7. int tlen=str.length();
  8. vector<vector<string> > nums(tlen+1,vector<string>(k+1));
  9. string s1,s2;
  10. for(int i=1;i<=tlen;i++){
  11. for(int j=0;j<i && j<=k;j++){
  12. if(j==0){
  13. nums[i][j]=str.substr(0,i);
  14. }
  15. else{
  16. s1=nums[i-1][j-1];
  17. s2=nums[i-1][j]+str[i-1];
  18. if(s1.compare(s2)<=0)
  19. nums[i][j]=s2;
  20. else
  21. nums[i][j]=s1;
  22. }
  23. }
  24. }
  25. return nums[tlen][k];
  26. }
  27. // dynamic programming
  28. // time complexity: O(n*k)
  29. // space complexity: O(k)
  30. string deleteKBits_3(string str,int k){
  31. int tlen=str.length();
  32. vector<string> nums(k+1);
  33. string s1,s2,last;
  34. for(int i=1;i<=tlen;i++){
  35. for(int j=0;j<i && j<=k;j++){
  36. if(j==0){
  37. last=nums[j];
  38. nums[j]=str.substr(0,i);
  39. }
  40. else{
  41. // s1=last
  42. s1=nums[j-1];
  43. s2=nums[j]+str[i-1];
  44. if(s1.compare(s2)<=0){
  45. last=nums[j];
  46. nums[j]=s2;
  47. }
  48. else{
  49. last=nums[j];
  50. nums[j]=s1;
  51. }
  52. }
  53. }
  54. }
  55. return nums[k];
  56. }
  57. // dynamic programming
  58. // time complexity: O(n*k)
  59. // space complexity: O(k)
  60. string deleteKBits_4(string str,int k){
  61. int tlen=str.length();
  62. vector<string> nums(k+1);
  63. string tmp,s2,last;
  64. for(int i=1;i<=tlen;i++){
  65. for(int j=0;j<i && j<=k;j++){
  66. if(j==0){
  67. last=nums[j];
  68. nums[j]=str.substr(0,i);
  69. }
  70. else{
  71. // s1=last
  72. // s1=nums[j-1];
  73. s2=nums[j]+str[i-1];
  74. if(last.compare(s2)<=0){
  75. last=nums[j];
  76. nums[j]=s2;
  77. }
  78. else{
  79. tmp=nums[j];
  80. nums[j]=last;
  81. last=tmp;
  82. }
  83. }
  84. }
  85. }
  86. return nums[k];
  87. }
  88. int main()
  89. {
  90. string str="2319274";
  91. int k=3;
  92. cout <<deleteKBits_2(str,k)<< endl;
  93. cout <<deleteKBits_3(str,k)<< endl;
  94. cout <<deleteKBits_4(str,k)<< endl;
  95. system("pause");
  96. return 0;
  97. }