算法第四章实践报告
1、实践题目:
7-2 删数问题 (110 分)
2、问题描述:
给定n位正整数a,去掉其中任意k≤n 个数字后,剩下的数字按原次序排列组成一个新 的正整数。对于给定的n位正整数a和正整数 k,设计一个算法找出剩下数字组成的新数最 小的删数方案。
输入格式:
第 1 行是1 个正整数 a。第 2 行是正整数k。
输出格式:
输出最小数。
比如第一次输入: 178543
再次输入: 4
那么将得出的输出答案是: 13
3、算法描述:
我们删除数字时,应从高位开始删除,例如上面的范例数字178543,要从中删除4位数字使得剩下的数字最小,那么第一个应该删除的是数字8,然后删除的是7,再然后就是5,最后删除的是4,最终看到结果就是13。基于此想法,并总结出规律:按高位到低位的顺序搜索,若各位数字递增,则删除最后一个数字;否则删除第一个递减区间的首字符,这样删一位便形成了一个新的数字串。然后回到串首,按上述规则再删除下一个数字。删除之后,其他数字往前移动一位,填补位置。最后把剩下的几个数字,组成一个整数。
while (k--) { for (int i = 0; i < n; i++) { if (a[i] > a[i + 1]) { for (int j = i; j < n; j++) { a[j] = a[j + 1]; } break; } } }
4、算法时间及空间复杂度分析:
删数问题将字符串从头到尾遍历了一遍,如果前面的大于后面的就删掉,要遍历k遍,所以时间复杂度O(n*k)
空间复杂度跟数组大小有关,空间复杂度为O(n)
5、心得体会:
在做这道题时,经过和结对同学的激烈讨论,我们发现了删数的规律,并将其通过代码实现,但是在输出的时候遇到了一点问题,如何实现处理删除后的数字前面的0这个问题的代码让我们想了一段时间,最后终于找到了正确的能表达内心算法的代码,当最后得到的数前面好几位数字都是0时,设置一个m来标记第一个不为0的数字,从该位置m开始输出即可,
for (int i = 0; i < n; i++) { if (a[i] != '0') { m = i; break; } } for (int i = m; i < n; i++) { cout << a[i]; }
另外还有个小细节,当k=n的时候用我们的代码运行得到的输出是空的,于是我们又加了一个if语句设置这种情况下输出0 。该问题也用到了贪心的思想,贪心算法和动态规划类似,但没有动态规划那么繁琐,寻找问题的最优子结构这一步是关键。最后,还要感谢我的结对队友,如果没有你,就没有这么快乐高效的a题过程!当然还要感谢郑琪老师,教学严谨认真负责有趣,真的是位优秀的老师啊!