木又连续日更第18天(18/100)
木又的第178篇leetcode解题报告
贪心类型第7篇解题报告
leetcode第881题:救生艇
https://leetcode-cn.com/problems/boats-to-save-people
【题目】
第 i 个人的体重为 people[i],每艘船可以承载的最大重量为 limit。
每艘船最多可同时载两人,但条件是这些人的重量之和最多为 limit。
返回载到每一个人所需的最小船数。(保证每个人都能被船载)。
示例 1:
输入:people = [1,2], limit = 3
输出:1
解释:1 艘船载 (1, 2)
示例 2:
输入:people = [3,2,2,1], limit = 3
输出:3
解释:3 艘船分别载 (1, 2), (2) 和 (3)
示例 3:
输入:people = [3,5,3,4], limit = 5
输出:4
解释:4 艘船分别载 (3), (3), (4), (5)
提示: 1 <= people.length <= 50000 1 <= people[i] <= limit <= 30000
【思路】
最开始想的解法是:使用字典d存储各个体重及其人数,从limit遍历到1,只要该体重i有人,d[i] -= 1,并且结果计数加1,同时,遍历limit-i到1,只要体重j有人,d[j] -= 1(每条船只能容纳两人,故内层循环满足条件后必须continue)。最后返回结果。
伪代码如下:
for i in range(limit, 0, -1):
if d.get(i, 0) == 0:
continue
d[i] -=1
res += 1
for j in range(i, 0, -1):
if d.get(j, 0) > 0:
d[j] -= 1
continue
方法是可行的,但是时间复杂度太高,O(limit^2)
在网上看到一个解法:将体重进行排序,使用两个指针left和right,分别指向未上船的最轻的人和最重的人,每条船肯定能容纳最重的人,可能能容纳最轻的人,于是,判断people[left] + people[right] <= limit是否成立,如果成立,right--,left++,否则只是right--。返回right移动次数。
【代码】
python版本
class Solution(object):
def numRescueBoats(self, people, limit):
"""
:type people: List[int]
:type limit: int
:rtype: int
"""
people.sort()
left, right = 0, len(people) - 1
count = 0
while left <= right:
if people[left] + people[right] <= limit:
left += 1
right -= 1
count += 1
return count
C++版本
class Solution {
public:
int numRescueBoats(vector<int>& people, int limit) {
sort(people.begin(), people.end());
int left = 0, right = people.size() - 1;
int count = 0;
while(left <= right){
if(people[left] + people[right] <= limit)
left++;
right--;
count++;
}
return count;
}
};