算法随笔_24: 救生艇

上一篇:算法随笔_23: 通过删除字母匹配到字典里最长单词-CSDN博客

======

题目描述如下:

给定数组 people 。people[i]表示第 i 个人的体重 ,船的数量不限,每艘船可以承载的最大重量为 limit

每艘船最多可同时载两人,但条件是这些人的重量之和最多为 limit

返回 承载所有人所需的最小船数 。

示例 1:

输入:people = [1,2], limit = 3
输出:1
解释:1 艘船载 (1, 2)

======

算法思路:

题目需要求出承载所有人所需的最小船数 。那么我们需要尽可能的让一条船承载更多的人。但题目要求一条船最多能承载两人。因此,我们应该尽可能的让每个人都有一个同伴乘坐同一条船。这样的话,可以达到最少可能船数,那就是总人数除以2之后向上取整。题目中还有一个条件,船上所有人的重量之和必须小于等于limit。因此我们可以得出下面的一推论:

1. 一个人的重量如果大于等于limit,他一定没有同伴,需要单独乘坐一条船。

2.  现在我们只考虑小于limit的那群人。这群人中最重的那个人p_heavy,尝试和最轻的人p_light组成一组,有下面两种情况:

   a.  如果和最轻的人p_light重量之和大于limit,那就说明他和其他的人都不可能组成一组,所以他也肯定没有同伴。

   b. 如果和p_light的重量之和小于等于limit,那就说明他和其他的人也有可能组成一组。至少他会有一个同伴。那p_heavy选哪个人做同伴呢?在这里我们选择和最轻的人做同伴,且不会对最终结果有影响。下面我们尝试证明这点:

***********

假设小于limit的那群人有60个人,重量从小到大排列,分别为p1到p60,p1就是p_light,p60就是p_heavy。假如p_heavy可以和p1到p30之间的任何人做同伴,即重量之和小于等于limit。不失一般性的,我们在假设p_heavy选择p15做为同伴之后,得到了题目的最优解。这个最优解无非包含下面两种情况:

1)  p1单独一组。

2)  p1和p60以下的任何一个人一组。如:p59

对于第一种情况,我们让p15乘坐p1那条船,让p1和p_heavy一组。最终的船数不变。

对于第二种情况,我们让p15和p59一组,让p1和p_heavy一组。由于p15可以和p_heavy一组,且p59比p_heavy轻,所以让p15和p59一组也是符合条件的。这样一来,船数也不改变。

***********

因此,我们让p_heavy和最轻的人一组,对最终结果无影响。

我们把上面全部的分析整理一下,基本上就可以写出这道题的算法了。但最后的代码实现可能跟上面的算法多少有一些出入,所以为了让大家更清晰的理解最终的代码实现,我们先依据上面的分析写出下面第一版本的算法:

1.  把people数组从小到大排序。设两个指针,p1和p2。p1指向数组的开始。p2指向数组的末尾。设数组res为最终的分组。此时res的每个元素也是一个数组。

2.  p2从右往左开始枚举数组。

   a. 对于大于等于limit的元素,我们让它自己成为一组,并把它放入res中。

   b.  对于小于limit的元素,我们让它和p1所指元素相加,并判断是否小于limit。

      b1)  如果小于等于limit,我们把p1和p2组成一组,并把它放入res中。p1向右移动一格。

      b2)  如果大于limit,我们让它p2自己成为一组,并把它放入res中。

p2向左移动一格,重复步骤2。

当p1>=p2时算法退出。如果此时p1==p2,也需要让p2自己成为一组,并把它放入res中。

最终计算res的长度即为答案。

对于最终的代码实现,我们可以简化一下上面的算法。对于上面提到的2a的情形,我们可以把它合并到2b中判断,因为本身2a的情形就是大于等于limit,它即便加上最轻的人也必然大于limit,所以合并到2b判断并不影响最终结果。

对于存放分组的res我们也不需要把一对儿的值都存下来。我们只存p2即可。这时,res的每一个元素就是一个数值。

下面就是最终的代码实现:

class Solution(object):
    def numRescueBoats(self, people, limit):
        """
        :type people: List[int]
        :type limit: int
        :rtype: int
        """
        people.sort()
        p_len=len(people)
        p1=0
        p2=p_len-1
        res=[]
        while p1

本文力求将这个问题阐述得通俗易懂且详尽细致,以便大家能够更好地理解这道题的算法思路。

你可能感兴趣的:(算法)