题目:
给定n位正整数a,去掉其中任意k≤n 个数字后,剩下的数字按原次序排列组成一个新 的正整数。对于给定的n位正整数a和正整数 k,设计一个算法找出剩下数字组成的新数最 小的删数方案。
输入:
第 1 行是1 个正整数 a。第 2 行是正整数k
输出:
输出最小数。
输入样例:
178543
4
输出样例:
13
题目思路:
假设我们先只删去一个数,那么我们删了这个数后,这个数的后面一个数就会往前补充我删去的这一位的位置。假设向前补位的数是比我们选择删去的数大,那么结果肯定不是最小值。
比如:123845.删去3的话:12845,而理想的结果是12345.所以我们要删去大的这个数肯定是比他的后一位大的。这样才能使替补位是小的。
于是乎,只要从左往右,找到上升序列的末尾元素,即一个小峰值,删去这个数即可。之后继续,删多少位就找多少个峰值。在删一个后找峰值,是从删除后的序列去找的。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
string s;
int k;
int a[10005];
int main(){
string s;
cin>>s>>k;
for(int i=0;i<s.size();i++){
a[i]=s[i]-'0';
}
int len=s.size();
while(k--){
for(int i=0;i<len;i++){
if(a[i]>a[i+1]){
for(int j=i;j<len;j++){
a[j]=a[j+1];
}
len--;
break;
}
}
}
int flag=0;
for(int i=0;i<len;i++){
if(a[i]!=0){
flag=1;
cout<<a[i];
}else if(flag==1){
cout<<a[i];
}
if(i==len-1 && flag==0){
cout<<0;
}
}
return 0;
}
注意点:
有可能删去之后,出现00001000这样的情况,所以,要先判断有没有除零之外的其他数的存在,用flag来标记,如果有,开启输出,如果没有就表明这个数字只要0,那么只需要输出一个0即可。
算法时间复杂度分析:
由于删去一个数需要后面的数组往前移,所以一次操作最大位N,最小为0,平均N+0/2 = N/2.如果极端情况删去所有的数,那么时间为n-1+(n-2)+(n-3)+……+0 ,所以最终的时间复杂度为O(N^2)
算法心得:
其实一开始觉得贪心嘛,套路就是最大最小,但其实不一定,这道题就是。只是阶段性的最大最小。所以还是不要被贪心迷惑。