(笔试题)删除K位数字
题目:
现有一个 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位数字的更多相关文章
- Leetcode 402.移掉k位数字
移调k位数字 给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小. 注意: num 的长度小于 10002 且 ≥ k. num 不会包含任何前导零. 示例 1 : ...
- 算法46----移除K位数字
一.题目:移除K位数字 给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小. 注意: num 的长度小于 10002 且 ≥ k. num 不会包含任何前导零. 示 ...
- 402. 移掉K位数字
给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小. 注意: num 的长度小于 10002 且 ≥ k.num 不会包含任何前导零.示例 1 : 输入: num ...
- [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 ...
- LeetCode:移除K位数字【402】
LeetCode:移除K位数字[402] 题目描述 给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小. 注意: num 的长度小于 10002 且 ≥ k. nu ...
- 402 Remove K Digits 移掉K位数字
给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小.注意: num 的长度小于 10002 且 ≥ k. num 不会包含任何前导零.示例 1 :输入: ...
- Java实现 LeetCode 402 移掉K位数字
402. 移掉K位数字 给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小. 注意: num 的长度小于 10002 且 ≥ k. num 不会包含任何前导零. 示 ...
- 算法——移掉K位数字使得数值最小
给定一个以字符串表示的非负整数 num,移除这个数中的 k 位数字,使得剩下的数字最小. leetcode 解题思路:如果这个数的各个位是递增的,那么直接从最后面开始移除一定就是最最小的:如果这个数的 ...
- [LeetCode] Remove K Digits 去掉K位数字
Given a non-negative integer num represented as a string, remove k digits from the number so that th ...
随机推荐
- 【20181103T1】地球发动机【dp优化】
题面 一眼dp 设\(f_i\)表示前\(i\)个且\(i\)必须选的最大功率 有 \(f _i= max_{1 \leq j < i,A_i - A_j > X_j} \{f_j \}+ ...
- 【漏洞预警】Apache ActiveMQ Fileserver远程代码执行漏洞(CVE-2016-3088)
漏洞编码:CVE-2016-3088 实验环境:Linux Apache ActiveMQ版本号:Apache ActiveMQ 5.7.0 ----------------------------- ...
- windows控制台程序——关于UNICODE字符的总结(转)
前言:从Windows NT/2000开如,Windows系统已经是一个标准的UNICODE系统,系统内部所有字符串存储及操作均使用UNICODE编码.因此Win32 API都是UNICODE版本的, ...
- phpcms功能列表
上1 站点首页 就是前台首页 会员中心 跳到会员中心页面 搜索 新闻,图片等文档搜索 锁屏 锁住账号 Phpcms 官网 授权 官网查询 支持论坛 官网论坛 帮助 官网帮助 上2 我的面板 个人信息 ...
- Android - Mount a Samba share
Mount Manager, Cifs manager :Manage your CIFS/NFS network shares was working, but the command from t ...
- Clever Little Box 电缆组件 USB A 插头 至 USB B 插头
http://china.rs-online.com/web/p/usb-cable-assemblies/7244143/ 产品详细信息 USB3.0适配器 superspeed USB将提供10x ...
- xvcd – The Xilinx Virtual Cable Daemon
http://debugmo.de/2012/02/xvcd-the-xilinx-virtual-cable-daemon/ I recently discovered an almost undo ...
- vim选择命令
最近在做一些无聊的客户化OSD,发现结合vim的一些命令更简单. 1.全选:ggVG(V:shift+v) 解释是:gg 让光标移到首行,在vim才有效,vi中无效:V 是进入Visual(可视)模式 ...
- Introducing .NET Core
At connect(), we announced that .NET Core will be entirely released as open source software. I also ...
- MVC二级联动使用$.getJSON方法
本篇使用jQuery的$.getJSON()实现二级联动. □ View Models 1: namespace MvcApplication1.Models 2: { 3: public cla ...