实践题目:删数问题


问题描述:

4-2 删数问题 (110 分)

给定n位正整数a,去掉其中任意k≤n 个数字后,剩下的数字按原次序排列组成一个新 的正整数。对于给定的n位正整数a和正整数 k,设计一个算法找出剩下数字组成的新数最 小的删数方案。

输入格式:

第 1 行是1 个正整数 a。第 2 行是正整数k。

输出格式:

输出最小数。

输入样例:

在这里给出一组输入。例如:

178543
4

输出样例:

在这里给出相应的输出。例如:

13

算法描述:

这里这道题需要用到贪心算法,贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。(百度百科)

但是和常见简单的贪心算法不一样的是,为了让删数后的数最小,高位应该尽可能的小,所以在使用贪心算法策略的时候应该从最高位作比较删除。

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;

int main(){
    int n, i, j, k;
    string a;

    cin>>a>>n;
    int len=a.size();

    //删数过程(删掉k个数) 
    for(k=0; k<n; k++){
        for(i=0; i<len-1; i++){
            //从最高位开始比较,若a[i] > a[i+1](高位比地位的数字更大),该位后面所有位往前挪一位(删掉a[i])
            if(a[i] > a[i+1]){
                for(j=i; j<len-1; j++)
                    a[j] = a[j+1];
                break;
            }
        }
        //删掉一位后len--
        len--;
    }

    i = 0;
    //删数最后的数以0开头
    while(i <= len-1 && a[i] == '0')i++;

    //若全为0的情况
    if(i == len)
        cout<<"0"<<endl;
    //从第一个非0开始输出
    else
        for(j=i; j<=len-1; j++)
            cout<<a[j];

    return 0;
}

算法时间及空间复杂度分析:

删数过程中,k次循环删数中嵌套两个与输入字符串长度n相关的循环,则时间复杂度为:O(k*n*n)

删数完成之后,一次检查0的循环:O(n)

则最后的时间复杂度为:O(n²)


心得体会:

多刷题,多思考,多总结。

01-06 21:13