题目背景】题目是:假设正整数n、s,s<n。设计算法对任一给定n位数,删除其中的s位后,使得剩下的位组成的新数最小。
例如:n = 6,s = 3,如果组成的6位数字是783259,那么删除3位数字后,那么剔除3位后最小的数字应该是259。再比如,n = 5,s = 2,如果组成的5位数字是24351,那么剔除2位的最小数字是231。
【解题算法】这里给出的是使用贪心法解决这个问题。至于其他算法,希望大家集思广益,给出更好的解法额。所谓贪心法:在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的仅是在某种意义上的局部最优解。
【解题思路】我们把n位的数字放到数组中,使用循环剔除不符合要求的数字。每次循环总是将一个使剩下的数最小的数字剔除,即按高位到低位的顺序搜索,若各位数字递增,则删除最后一个数字,否则删除第一个递减区间的首字符。
【解题代码】查看代码
<?php //调用函数 delete(7 , 3); /** * 贪心法实例 * $n n位数 * $s 删除s位数 **/ function delete($n, $s){ if ($n < $s) { die('error'); } //根据输入的n,随机获取n位数 $number = array(); for ($i = 0; $i < $n; $i++) { if ($i == 0) { $temp = mt_rand(1, 9); } else { $temp = mt_rand(0, 9); } $number[] = $temp; } echo str_replace(',', '', implode(',', $number)) . "<br />"; //循环剔除不符要求的数字 while(count($number) > $n - $s) { $count = count($number); for ($i = 0; $i < $count; $i++) { if ($i == $count - 1) { //循环到最后一个元素,即剔除最后一位数字 unset($number[$i]); break; } elseif ($i <= $count - 2 && $number[$i] > $number[$i + 1] && ($number[$i + 1] > 0 || $i > 0)){ //元素间两两比较,前者比后者大时,满足以下条件之一即剔除前者 //1、后者大于0 //2、前者非第一个元素 unset($number[$i]); break; } } $number = array_values($number); } echo str_replace(',', '', implode(',', $number)); } ?>
看到这里,各位有没有更好的解法呢?在回复里贴出你的代码来吧!
其实贪心算法的经典题目有很多,这里只是举了一个列子,比如马踏棋盘的贪心算法,背包问题的贪心算法。各位有兴趣的可以自己去研究下额!