算法第四章上机实验报告

4-2 删数问题 (30 分)

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

输入格式:

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

输出格式:

输出最小数。

输入样例:

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

178543 
4 
 
5001 
1
 
123456 
2
 
109 
1
 
 

输出样例:

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

13
 
1
 
1234
 
9

代码
#include<bits/stdc++.h>
using namespace std;
string a;
int t; 
int main() 
{
    cin >> a;
    scanf("%d", &t);
    while(t--) 
    {
        int pos = 0;//找每次要删除的位置
        char ma = a[0];//从前往后的第一个连续递增序列的末尾,先假设为第一个元素
        for(int i = 1; i < a.size(); i++) 
        {
            if(a[i] < ma)//不再递增,说明前一个值在连续递增序列中是最大的
            {
                pos = i - 1;//记录下标
                break;
            }
            else ma = a[i];//递增,更新末尾
        }
        a.erase(pos, 1);//删除 从前往后的第一个连续递增序列的末尾
        if(a.size()==0)
        {
            cout << 0;
            return 0;
        }
        while(a.size() > 1 && a[0]=='0')//删除前导零
        {
            a.erase(0, 1);
        }
    }
    for(int i = 0; i < a.size(); i++) //输出
        if(isdigit(a[i])) cout << a[i];
    return 0;
}

贪心策略:

每次从前往后找第一个连续递增序列的末尾,这样可以使删除末尾后的值是最小的。

举例:

135826 删除一个数

从前往后第一个连续递增序列为 1358 , 删除8, 得13526;

如果不删除8, 删除 5 或 2 , 分别得到 13826, 13586;都比13526要大。

因此贪心策略无误。(最好多找几个数据来测试贪心策略,我已经测试过了)

最后注意

前导零不要忘了去除!

时间复杂度:O(t*n) 

n为a的长度

我对贪心算法的理解

贪心算法是不从整体最优上加以考虑,它所做出的是在某种意义上的局部最优解。

确定题目用贪心算法时,首先确定贪心策略,选择一个看上去最好的方案。其次考虑局部最优解,把问题分成一个个小问题。最后

自然就得出了整个问题的最优解。

posted @ 2021-11-12 19:07  haiou、  阅读(44)  评论(0编辑  收藏  举报