在问 · 算法题解

881. 救生艇

题目描述

输入数组 people 和整数 limit,people[i] 是第 i 个人的体重。船的数量不限。

每艘船最多坐两个人,并且船上人的体重之和不能超过 limit。保证每个人的体重都不超过 limit。

返回把所有人都运走最少需要多少艘船。

示例 1
输入:people = [1,2], limit = 3
输出:1

解释:两人体重和为 3,坐一艘船即可。

示例 2
输入:people = [3,2,2,1], limit = 3
输出:3

解释:分为 (1,2)、(2)、(3) 三艘。

示例 3
输入:people = [3,5,3,4], limit = 5
输出:4

解释:任意两人体重和都超过 5,只能每人一艘。

数据范围

  • 1 <= people.length <= 5 * 10^4
  • 1 <= people[i] <= limit <= 3 * 10^4

解题思路

先排序。最重的人一定要上船,问题是能不能给他配一个同伴。最有希望的同伴是最轻的人:如果最轻的人都配不上,别人更不可能,最重的人只能单独坐;如果能配上,让他们同船不会更差,因为最轻的人和谁坐都只占一个名额。用双指针 i(最轻)和 j(最重)向中间收缩。

为什么正确

people[:i] 和 people[j+1:] 已经上船,boats 是已经用掉的船数;剩下的 people[i..j] 还在岸上。

复杂度分析

时间 O(n log n)(排序),额外空间 O(1)(不计排序栈)。

易错点

从最轻的人开始两两凑满,或者给最重的人找“刚好能配”的最重同伴,都会让思路变复杂。只要比较最轻和最重即可;另外 i == j 时只剩一人,也要算一艘船。

参考代码

Python、Java、C++、Go、JavaScript、TypeScript 六种语言,逻辑一致。

class Solution:
    def numRescueBoats(self, people: List[int], limit: int) -> int:
        people.sort()
        i, j = 0, len(people) - 1
        boats = 0
        while i <= j:
            if people[i] + people[j] <= limit:
                i += 1
            j -= 1
            boats += 1
        return boats

载入编辑器,自己跑一遍 →

贪心 专题的其他题目

查看 贪心 全部题目 →