题目:

现有一个 n 位数,你需要删除其中的 k 位,请问如何删除才能使得剩下的数最大?

比如当数为 2319274, k=1 时,删去 2 变成 319274 后是可能的最大值。

思路:

1、贪心算法

每次从高位向低位数,删除高位数字比低位数字小的那位数字。如2319274

第一次2<3,删除2,得到319274

第二次3>1,略过,1<9,删除1,得到39274

第三次3<9,删除3,得到9274

。。。。。。

  1. // greedy method
  2. string deleteKBits_1(string str,int k){
  3. int tlen=str.length();
  4. bool flag=true;
  5. int len;
  6. while(k && flag){
  7. len=str.length();
  8. for(int i=0;i<len-1;i++){
  9. if(str[i]<str[i+1]){
  10. str.erase(i,1);
  11. flag=true;
  12. break;
  13. }
  14. }
  15. k--;
  16. }
  17. return str.substr(0,tlen-k);
  18. }

2、动态规划

分析:

假设str为长度为n的数字字符串,S[i][j]表示删除str[0...i-1]中j个数字后的最大字符数字。

如果删除第i个数,则S[i][j]等于删除前i-1个字符中的j-1位的最优解,即S[i][j]=S[i-1][j-1];

如果不删除第i个数,则S[i][j]等于删除前i-1个字符中j位的最优解+str[i],即S[i][j]=S[i-1][j]+str[i-1];

即S[i][j]=max(S[i-1][j-1],S[i-1][j]+str[i-1])

初始状态为当j=0时,不删除任何位的数字,即S[i][j]=str[0...i-1];

状态转移方程如下:

S[i][j]=

strsub(0,i); (if j==0)

max(S[i-1][j-1],S[i-1][j]+str[i-1]); (if 0<j<i;0<j<=k)

时间复杂度:O(n*k)

空间复杂度:O(n*k)

优化:

从上述的转移方程S[i][j]=max(S[i-1][j-1],S[i-1][j]+str[i-1]),可以看出在每一次i循环中,只与i-1相关,因此不需要用单独使用一个维度的数组来存储,只需要每次通过一个变量last保存上一次的结果。因此转移方程可以简化为S[j]=max(last,S[j]+str[i-1])

时间复杂度:O(n*k)

空间复杂度:O(k)

  1. // dynamic programming
  2. // time complexity: O(n*k)
  3. // space complexity: O(n*k)
  4. string deleteKBits_2(string str,int k){
  5. int tlen=str.length();
  6. vector<vector<string> > nums(tlen+1,vector<string>(k+1));
  7. string s1,s2;
  8. for(int i=1;i<=tlen;i++){
  9. for(int j=0;j<i && j<=k;j++){
  10. if(j==0){
  11. nums[i][j]=str.substr(0,i);
  12. }
  13. else{
  14. s1=nums[i-1][j-1];
  15. s2=nums[i-1][j]+str[i-1];
  16. if(s1.compare(s2)<=0)
  17. nums[i][j]=s2;
  18. else
  19. nums[i][j]=s1;
  20. }
  21. }
  22. }
  23. return nums[tlen][k];
  24. }
  25.  
  26. // dynamic programming
  27. // time complexity: O(n*k)
  28. // space complexity: O(k)
  29. string deleteKBits_3(string str,int k){
  30. int tlen=str.length();
  31. vector<string> nums(k+1);
  32. string s1,s2,last;
  33. for(int i=1;i<=tlen;i++){
  34. for(int j=0;j<i && j<=k;j++){
  35. if(j==0){
  36. last=nums[j];
  37. nums[j]=str.substr(0,i);
  38. }
  39. else{
  40. // s1=last
  41. s1=nums[j-1];
  42. s2=nums[j]+str[i-1];
  43. if(s1.compare(s2)<=0){
  44. last=nums[j];
  45. nums[j]=s2;
  46. }
  47. else{
  48. last=nums[j];
  49. nums[j]=s1;
  50. }
  51. }
  52. }
  53. }
  54. return nums[k];
  55. }
  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. }

运行结果:

  1. int main()
  2. {
  3. string str="2319274";
  4. int k=3;
  5. cout <<deleteKBits_1(str,k)<< endl;
  6. cout <<deleteKBits_2(str,k)<< endl;
  7. cout <<deleteKBits_3(str,k)<< endl;
  8. cout <<deleteKBits_4(str,k)<< endl;
  9. return 0;
  10. }

 

(笔试题)删除K位数字的更多相关文章

  1. Leetcode 402.移掉k位数字

    移调k位数字 给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小. 注意: num 的长度小于 10002 且 ≥ k. num 不会包含任何前导零. 示例 1 : ...

  2. 算法46----移除K位数字

    一.题目:移除K位数字 给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小. 注意: num 的长度小于 10002 且 ≥ k. num 不会包含任何前导零. 示 ...

  3. 402. 移掉K位数字

    给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小. 注意: num 的长度小于 10002 且 ≥ k.num 不会包含任何前导零.示例 1 : 输入: num ...

  4. [Swift]LeetCode402. 移掉K位数字 | Remove K Digits

    Given a non-negative integer num represented as a string, remove k digits from the number so that th ...

  5. LeetCode:移除K位数字【402】

    LeetCode:移除K位数字[402] 题目描述 给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小. 注意: num 的长度小于 10002 且 ≥ k. nu ...

  6. 402 Remove K Digits 移掉K位数字

    给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小.注意:    num 的长度小于 10002 且 ≥ k.    num 不会包含任何前导零.示例 1 :输入: ...

  7. Java实现 LeetCode 402 移掉K位数字

    402. 移掉K位数字 给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小. 注意: num 的长度小于 10002 且 ≥ k. num 不会包含任何前导零. 示 ...

  8. 算法——移掉K位数字使得数值最小

    给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小. leetcode 解题思路:如果这个数的各个位是递增的,那么直接从最后面开始移除一定就是最最小的:如果这个数的 ...

  9. [LeetCode] Remove K Digits 去掉K位数字

    Given a non-negative integer num represented as a string, remove k digits from the number so that th ...

随机推荐

  1. nginx与Lua执行顺序

    Nginx顺序 Nginx 处理每一个用户请求时,都是按照若干个不同阶段(phase)依次处理的,而不是根据配置文件上的顺序. Nginx 处理请求的过程一共划分为 11 个阶段,按照执行顺序依次是 ...

  2. 2017-2018-1 20162307 Dijkstra算法

    2017-2018-1 20162307 Dijkstra算法 题目要求 Dijkstra算法,求解附图顶点A的单源最短路径 在纸上画出求解过程,上传截图(注意图上要有自己的学号和姓名) 解题步骤

  3. SQL SERVER 扩展属性的操作方法

    将数据库迁移到 Azure SQL 数据库时出现错误,不支持扩展属性“MS_Description”,因此就如何操作扩展属性进行在此记录. 查询扩展属性 SELECT *,OBJECT_NAME(ma ...

  4. 【洛谷】4917:天守阁的地板【欧拉函数的应用】【lcm与gcd】【同除根号优化】

    P4917 天守阁的地板 题目背景 在下克上异变中,博丽灵梦为了找到异变的源头,一路打到了天守阁 异变主谋鬼人正邪为了迎击,将天守阁反复颠倒过来,而年久失修的天守阁也因此掉下了很多块地板 异变结束后, ...

  5. ASP.NET MVC HttpVerbs.Delete/Put Routes not firing

    原文地址: https://weblog.west-wind.com/posts/2015/Apr/09/ASPNET-MVC-HttpVerbsDeletePut-Routes-not-firing ...

  6. HDU4548+筛素数

    先筛出素数,再筛出美素数. 简单题. /* 筛素数 */ #include<stdio.h> #include<string.h> #include<stdlib.h&g ...

  7. list C++实现

    模仿STL中list,实现了其大部分功能.list可以高效地利用内存资源,常数时间的插入删除操作.并且,list除了erase外,不怎么存在迭代器失效的现象. #include<iostream ...

  8. 21扩展IEnumerable<T>泛型接口自定义LINQ的扩展方法

    LINQ方法实际上是对IEnumerable<TSource>的扩展,如图:   本篇自定义一个MyWhere方法,达到与Where相同的效果.     使用LINQ自带的Where方法 ...

  9. Linux 操作当前时间

    一.查看和修改Linux的时区 1. 查看当前时区 命令 : "date -R" 2. 修改设置Linux服务器时区 方法 A 命令 : "tzselect" ...

  10. 【ELK】【docker】【elasticsearch】1. 使用Docker和Elasticsearch+ kibana 5.6.9 搭建全文本搜索引擎应用 集群,安装ik分词器

    系列文章:[建议从第二章开始] [ELK][docker][elasticsearch]1. 使用Docker和Elasticsearch+ kibana 5.6.9 搭建全文本搜索引擎应用 集群,安 ...