算法第四章实践报告

1.1问题描述--删数问题 

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

输入格式:

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

输出格式:

输出最小数。

1.2 算法描述

1.2.1 贪心算法:

    首先得到局部的最优解,从而推导出全局的最优解。

1.2.2 本题解析:

题目要求在给出的正整数中剔除最大的k位,输出剩下的位数,且最前面的0不输出。在删除数字中,每一步删除操作是一个局部问题,每一步总是选择一个使剩下的数最小的数字删去,按高位到低位的顺序搜索。因此我们可以将其排列,每次只需要删除升序序列的尾部或者降序序列的头部,并且循环k次。

第一步,178543中取出一个数字,应该选取8;

第二步,17543中取出一个数字,应该选取7;

第三步,1543中取出一个数字,应该选取5

···

在第一步删除数时,从左到右可以找到一个部分升序:178

                  从右到左也可以找到一个部分降序:8543

因此,8恰好是升序的最后以及降序的开头。

在第二步删除数时,从左到右可以找到一个部分升序:17

                  从右到左也可以找到一个部分降序:7543

因此,7恰好是升序的最后以及降序的开头。

    ···

我们的贪心策略就是寻找最大数问题,并剔除其所在的位置,找到第一个升序数列的同时取出其末尾。递归k次合并成原问题。

1.2.3 伪代码

定义自变量:char a[300]; int k、len;

递归取数:while k!=0 do {                     //预防不删数的特殊情况

           While n[i]<=n[i+1] do i++          //保证升序

           While i<len-1 do n[i] = n[i+1]; i++ //取出第i个数

           Len--;k--    //保证取出完毕后,长度减小,需要循环次数减少

           }

输出处理:for i<len do{

           If n[i]=0&i<len-1 do continue

           Else cout

           i++

}

1.2.4 复杂度分析

时间复杂度:n

空间复杂度:n

1.3 心得体会(对本次实践收获及疑惑进行总结)

    通过本题,我对char类型数组有了更深入的理解。当我接触到本题时,第一个反应是运用数学运算&&设立flag辅助列表记录数字所在位数——个十百千等,但在实现中处处碰壁,总是报错。于是通过观察,转换思路,使用char类型&&升序找末尾的方法,但在处理输出时再次碰壁。因为输出是不能有0,只有100而没用0100,所以输出需要用if判断,给0作“分流”。贪心算法其实和人类心里很符合,总是寻求性价比最高,找最大,找最小。

posted @ 2021-11-16 20:07  小二脸  阅读(35)  评论(0编辑  收藏  举报