第四章编程总结

题目:

给定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)

算法心得:

其实一开始觉得贪心嘛,套路就是最大最小,但其实不一定,这道题就是。只是阶段性的最大最小。所以还是不要被贪心迷惑。

原文地址:https://www.cnblogs.com/aresjohnson/p/11887063.html