题目:

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

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

思路:

1、贪心算法

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

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

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

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

。。。。。。

// greedy method
string deleteKBits_1(string str,int k){
int tlen=str.length();
bool flag=true;
int len;
while(k && flag){
len=str.length();
for(int i=0;i<len-1;i++){
if(str[i]<str[i+1]){
str.erase(i,1);
flag=true;
break;
}
}
k--;
}
return str.substr(0,tlen-k);
}

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)

// 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_1(str,k)<< endl;
cout <<deleteKBits_2(str,k)<< endl;
cout <<deleteKBits_3(str,k)<< endl;
cout <<deleteKBits_4(str,k)<< endl;
return 0;
}

 

(笔试题)删除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. OI刷题记录(Updating)

    [Counter] [AGC]:0/96 [ARC]:0/70 [2016年省选]:0/69 [2017年省选]:22/75 [2018年省选]:0/63 [ZROI2018]:0/30 [ZROI2 ...

  2. Azure ServiceBus的消息中带有@strin3http//schemas.microsoft.com/2003/10/Serialization/�

    今天碰到一个很讨厌的问题,使用nodejs 接收Azure service bus队列消息的时候,出现了:@strin3http//schemas.microsoft.com/2003/10/Seri ...

  3. [USACO11DEC]Grass Planting

    题目大意: 有一棵结点个数为n的树,有m个操作,可以将一段路径上每条边的权值+1或询问某一个边的权值. 思路: 树链剖分+线段树. 轻重链划分本身比较简单,主要需要思考如何用线段树维护每条链. 当x, ...

  4. pygame系列_pygame安装

    在接下来的blog中,会有一系列的文章来介绍关于pygame的内容,所以把标题设置为pygame系列 在这篇blog中,主要描述一下我们怎样来安装pygame 可能很多人像我一样,发现了pygame是 ...

  5. Windows 7安装超级终端连接COM口设备

    Windows 7已经没有超级终端,只能用投机取巧的方式实现. 1.先配置电话 随便填写信息,然后点击确定即可. 2.下载这个终端运行,注意:要以管理员身份运行. 链接: https://pan.ba ...

  6. HTML5学习笔记4

    10.表单元素表单元素用于获取用户的输入数据form 表示HTML表单属性:    action 表示表单提交的页面    method 表示表单提交的请求方式:有POST和GET两种,默认GET(P ...

  7. JetBrains 系列软件汉化包

    原文地址:https://blog.csdn.net/pingfangx/article/details/78826145 JetBrains 系列软件汉化包 关键字: Android Studio ...

  8. Linux内核hlist数据结构分析

         在内核编程中哈希链表hlist使用非常多,比方在openvswitch中流表的存储中就使用了(见[1]).hlist的表头仅有一个指向首节点的指针.而没有指向尾节点的指针,这样在有非常多个b ...

  9. 3D数学读书笔记——四元数

    本系列文章由birdlove1987编写,转载请注明出处. 文章链接: http://blog.csdn.net/zhurui_idea/article/details/25400659 什么是四元数 ...

  10. TPS70345 (ACTIVE) 双路输出低压降 (LDO) 稳压器

    The TPS703xx family of devices is designed to provide a complete power management solution for TI DS ...