难度中等133
第 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
思路:排序+贪心+双指针,如果当前的最小值加上最大值不能满足<=limit的限制。那么这个最大值只能自己坐一艘船走,这样双指针走下去即可。
class Solution {
public:
int numRescueBoats(vector<int>& people, int limit) {
int n = people.size(), L = 0, R = n - 1, nums = 0;
sort(people.begin(), people.end());
while(L < R){
while(L < R && limit < people[L] + people[R]) {
++ nums;
-- R;
}
++ L;
-- R;
++ nums;
}
return nums + (L == R);
}
};
小优化:在初始化区间右指针的时候,可以直接二分搜索。
class Solution {
public:
int numRescueBoats(vector<int>& people, int limit) {
int n = people.size(), L = 0, R, nums;
if(n <= 1) return n;
sort(people.begin(), people.end());
vector<int>::iterator iter = upper_bound(people.begin(), people.end(), limit - people[0]);
if(iter == people.begin()) {//最小的值都找不到一个可以共乘船的人 那所有人都只能独自乘船
return n;
}
else {
R = iter - people.begin() - 1;
nums = n - R - 1;
}
while(L < R) {
while(L < R && limit < people[L] + people[R]) {
++ nums;
-- R;
}
++ L;
-- R;
++ nums;
}
return nums + (L == R);
}
};
值得注意的是,我们可能会认为有了满足要求的区间左右端点后,拿到端点长度m,会认为答案是m*(m-1)/2。但其实,并不一定是这样的。
假如 limit = 9
数组为:1 5 6 7 8
那么此时尽管1+8<=9,但是5+7并不满足,因此不能如此求解。