代码随想录算法训练营第三十天 |贪心算法part04

84 阅读3分钟

代码随想录算法训练营第三十天 |贪心算法part04

452 用最少数量的箭引爆气球

image.png

思路

  • 局部最优:当气球出现重叠,一起射,所用弓箭最少。
  • 全局最优:把所有气球射爆所用弓箭最少。
  • 为了让气球尽可能的重叠,需要对数组进行排序
  • 如果气球重叠了,重叠气球中右边边界的最小值 之前的区间一定需要一个弓箭

代码如下:

首先我们需要进行排序

    points.sort(key=lambda x: x[0])
    result = 0

然后需要进行遍历,这里选择从1开始,因为不管怎么样,只要有气球就需要射一箭。

    for i in range(1,len(points)):
        if points[i][0] > points[i-1][1]: # 如果这一个左边界比上一个的右边界大,说明不重合
            result += 1
        # 如果重合了,那么就需要将这一个的右边界换成上一个的右边界和这一个的右边界的最小值
        # 重合以后我射两个重合的右边界的最小值即可。
        else :
            points[i][i] = min(points[i-1][1],points[i][1])

完整代码:

    if len(points) == 0: return 0
    points.sort(key=lambda x: x[0])
    result = 1
    for i in range(1, len(points)):
        if points[i][0] > points[i - 1][1]: # 气球i和气球i-1不挨着,注意这里不是>=
            result += 1     
        else:
            points[i][1] = min(points[i - 1][1], points[i][1]) # 更新重叠气球最小右边界
    return result

如下图所示:

image.png

435 无重叠区间

image.png

思路:首先进行排序,然后进行比较,这一个的右边界和上一个的左边界进行比较。然后更改右边界为两个右边界的最小值。

    intervals = [[-52,31],[-73,-26],[82,97],[-65,-11],[-62,-49],[95,99],[58,95],[-31,49],[66,98],[-63,2],[30,47],[-40,-26]]
    intervals.sort(key=lambda x: (x[0],x[1]))
    print(intervals)
    result = 0
    for i in range(1,len(intervals)):
        if intervals[i-1][1] > intervals[i][0]:
            intervals[i][1] = min(intervals[i - 1][1], intervals[i][1]) 
            result += 1
    print(result)

763 划分字母区间

image.png

思路:

在遍历的过程中相当于是要找每一个字母的边界,如果找到之前遍历过的所有字母的最远边界,说明这个边界就是分割点了。此时前面出现过所有字母,最远也就到这个边界了。

可以分为如下两步:

  • 统计每一个字符最后出现的位置
  • 从头遍历字符,并更新字符的最远出现下标,如果找到字符最远出现位置下标和当前下标相等了,则找到了分割点

image.png

首先先有一个字典,进行对s中每一个字符出现的位置进行存储,只存储一次,相当于只存储最后的位置

dic1 = {}
for i,ch in enumerate(s):
    dic1[ch] = i

然后现在就拥有了每个字符的最终位置,开始继续对s遍历

start = 0
end = 0 #初始化所有字符的最终位置为0
for i,ch in enumerate(s):
    end = max(end,dic1[ch]) # 现在end表示遍历到的所有字符里面最大的end
    if i == end : # 表示遍历到了当前分段的最后一个数,
        result.append(end - start + 1)
        start = i + 1
print(result)