用贪心算法处理删数问题

[size=medium] 其实对于算法,我确实研究的比较少,贪心算法也接触的不多,一次偶然的机会别人让叫我给他编个小程序,我才了解到那么一点点。
这个程序是这样的,从控制台输入一个N位的数字,删除其中的K(0<K<N)位,按原顺序组成一个最大的数字,输出这个数字, 如:1891456删除其中的4位后组成的最大数为:956。如果不知道贪心算法的人,乍一看这题目确实还要想下,其实难点就在于一定要按照原来的顺序组合,如果使用贪心算法就能使问题简化,你只要比较相邻两个数的大小,如果前面的比后面的小,就把前面的那个数给去掉,去掉后再重新开始比较,直到达到要求为止,一种极端的情况,如果所有数字都是按照升序排列的,那就更好办了,只要删除前面的几位就可以了。
其实我的想法也是来自别人算法,只是他用C++实现的,用到里面的函数库,使得这个程序很简单,因为我不懂C++,但我想C++和Java都是面向对象的语言,里面应该有很多功能相同的方法,结果查看文档还是被我找到了。其实这里关键就是怎样把比较后的那个数字给去掉的问题,想到过用数组,但它里面没有删除某个数后得到新数组的方法,后来突然发现了StringBuffer这个类,它里面有个deleteCharAt的方法,我觉得应该可以,并且用它的话还有个好处,你输入的数字不不受范围的约束,下面是我用Java实现的源码,还有原来参考的那个C++源码。我觉得实现的方法应该有很多,在此写出来只是为了相互学习,要是谁有更好的方法可以交流交流,共同进步。[/size]
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
删数问题是指给定一个正整数序列,每次可以选择其中的一个数并将其删去,最终使得序列中剩余的数组成的数最小。贪心算法可以解决这个问题,其正确性证明如下: 假设当前需要删去一个数,我们应该选择哪一个数呢?显然应该选择最高位最小的数,因为这样可以保证删去这个数后剩余的数字最小。具体来说,假设当前的数列为 $a_1,a_2,\dots,a_n$,我们应该找到最高位最小的数 $a_k$,其中 $k$ 满足 $a_k>0$ 且对于所有 $i<k$,有 $a_i=0$ 或者 $a_i=a_k$。然后删去这个数,并将剩下的数字重新组成一个新的序列。 这个贪心策略是正确的。首先可以证明它是一种可行的策略,即它能够得到一个合法的解。其次可以证明它是一种最优的策略,即它能够得到一个最小的解。 对于可行性,假设我们按照上述策略进行删数,得到了一个序列 $b_1,b_2,\dots,b_m$。我们需要证明这个序列是合法的,即它可以通过删数得到。假设原来的序列是 $a_1,a_2,\dots,a_n$。对于每个 $b_i$,我们可以在原来的序列中找到一个最高位最小的数 $a_j$,满足 $j$ 是尽可能小的满足 $a_j=b_i$ 的下标。由于 $b_i$ 是 $a_j$ 的最高位,因此在 $j$ 之前所有数都为 $0$ 或者与 $b_i$ 相等。因此我们可以将 $a_j$ 删去,并将剩余的数字重新组成一个新的序列。重复这个过程直到所有的 $b_i$ 都被处理完毕。 对于最优性,假设我们按照上述策略进行删数,得到了一个序列 $b_1,b_2,\dots,b_m$。我们需要证明这个序列是最优的,即不存在另外一种删数方案得到的序列比它更小。假设另外一种方案得到的序列为 $c_1,c_2,\dots,c_m$。由于我们按照最高位最小的原则进行选择,因此对于任意 $i$,都有 $b_i \leq c_i$。因此序列 $b_1,b_2,\dots,b_m$ 要么与序列 $c_1,c_2,\dots,c_m$ 相等,要么比它更小。 综上所述,我们证明了贪心算法是正确的,并且可以得到一个最优解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值