leetcode

来源:互联网 发布:淘宝图书抗日战争 编辑:程序博客网 时间:2024/06/05 01:03

算法系列博客之Greedy

Greedy 贪心算法是一种非常优美的算法,不过贪心算法本身的可行性很多时候会受到一些局限。但是一旦能够找到一种可行的贪心策略,问题的解决将会变得非常高效,因为通常情况下,贪心算法的复杂度是O(n)

本篇博客将运用这种思想来解决leetcode上452号问题


问题描述:

There are a number of spherical balloons spread in two-dimensional space. For each balloon, provided input is the start and end coordinates of the horizontal diameter. Since it’s horizontal, y-coordinates don’t matter and hence the x-coordinates of start and end of the diameter suffice. Start is always smaller than end. There will be at most 104 balloons.

An arrow can be shot up exactly vertically from different points along the x-axis. A balloon with xstart and xend bursts by an arrow shot at x if xstart ≤ x ≤ xend. There is no limit to the number of arrows that can be shot. An arrow once shot keeps travelling up infinitely. The problem is to find the minimum number of arrows that must be shot to burst all balloons.
题中的意思是说只要某个值既包含在气球A的活动范围也包含在气球B的活动范围,那么就可以一箭同时消灭这两个气球

我们的目的是要求出最少需要多少支箭,就可以消灭掉所有的气球
从贪心的角度来讲,只要保证每一箭都尽可能消灭多的气球,这样就能用尽可能少的箭支

单独对每个气球而言,要想消灭它,射出的箭支就必须在它的活动范围之内,对它贪心也就只能尽可能靠左、靠右或者靠中间
      ·   如果我们选择靠中间的策略,再来考虑对其它气球的影响,也就是箭支要尽量优先从比较集中的地方射出去
这样做无疑是增加了复杂度,即需要统计集中的数量
      ·   选择靠左或者靠右实际上是同一个原理,只是换了方向,如果选择靠右,那么至少这一支箭可以消灭掉当前状态下活动范围右侧端点在这个气球右侧端点之前的气球,这样我们就只需要先对气球按活动范围右侧端点进行排序即可

_ _ _ 此贪心策略的可行性和正确性证明 _ _ _:
      ·   对于第一支箭,如果它射出的位置在第一个气球右侧端点之前,这支箭能够消灭的气球数一定小于等于射出箭在右侧端点时的气球数
      ·   对于第 i 支箭,如果它射出的位置在此时留下的排在最左侧的气球右侧端点之前,这支箭能够消灭掉的气球数也一定小于等于射出箭在右侧端点时的气球数
      ·   而要想消灭掉每一步在最左侧的气球,就必须射出一支在其活动范围内的箭支,这是必要的。从第一步开始,每一步都在必要的前提下尽量消灭最多的气球,因而算法是可行且正确的

python代码实现如下:

class Solution(object):    def findMinArrowShots(self, points):        n = len(points)        if n == 0:            return 0        points.sort(cmp = lambda x,y : cmp(x[1], y[1]))        pre_arrow = points[0][1]        count = 1        for i in range(0, n):            if (pre_arrow < points[i][0]):                pre_arrow = points[i][1]                count += 1        return count

时间复杂度分析,如果抛开排序过程,此算法只剩下一层线性循环,复杂度为线性,但是此算法本身就依赖于排序,而排序的时间复杂度一般全都高于线性,因此此算法时间复杂度完全取决于排序算法的选择
空间复杂度分析,只需用到常数倍空间,因而O(1)
总体来讲,对这个算法也算是满意,因为算法教材上的贪心算法实例的复杂度也是依赖于排序算法的

0 0