unity3d 求两个点长度_算法题——[leetcode1637]不包含点的最宽条形区域

Medium级别的题:给定2维平面上若干个点,其一个最宽的条形区域(高度为无限长)使得其中不包含任何点——注意点在边界上不算包含。

数据范围:点数n满足2 <= n <= 100000, 所有点都是整点,坐标是不超过1000000000的非负整数。

例如:输入{{8, 7}, {9, 9}, {7, 4}, {9, 7}}返回1,如下图所示。

27f8cb0986e6866bceabb47916f6df69.png

分析:无聊题,只有x坐标有意义——其实是求所有x值排序后相邻两个值的差最大值。其实题目没说清楚,如果所有点x相同,答案应该是无穷大,而非0……

代码:

class Solution {public:    int maxWidthOfVerticalArea(vector<vector<int>>& points) {        sort(points.begin(), points.end());        int r = 0;        for (int i = 1; i < points.size(); ++i) {            r = max(r, points[i][0] - points[i - 1][0]);        }        return r;    }};

其实还有一种线性的分桶解法。利用抽屉原理,如果把n个点放入m个桶中,如果m > n,则至少有一个空桶。这里我们设mini和maxi分别是所有x值的最小和最大值。如果mini == maxi直接输出0(其实是无穷大)。

否则,我们把闭区间[mini, maxi]平均分成(n + 1)段。每段长度为(maxi - mini) / (n + 1) (不是整数除法,是实数,有理数)。

每一段是一个左闭右开的区间作为一个桶,为了方便,也为了每个点都在一个唯一的桶里,我们再设置一个长度为0的桶,即maxi本身在一个长度为0的桶里——因为是左闭右开的区间, maxi不在之前任何一个桶里。

于是我们有(n + 2)个桶。 每个x值放在一个桶里,对应编号为[(x - mini) * (n + 1) / (maxi - mini)] (下标从0开始,下取整)。

这些桶有很好的性质:

(1) 0号桶非空——因为mini在0号桶

  (2)  (n + 1)号桶非空——因为maxi在这个桶,这也是我们设置的changed为0的桶。

  (3) 中间必然至少有一个空桶,因为桶的数量比点的数量多。

这就告诉我们如果所有点排好序后,相邻的点差值的最大值一定不会小于桶的宽度——因为空桶左和右第一个点是相邻的,并且它们的距离不小于桶的宽度。 于是,我们可以对每个桶分别求最小值和最大值,然后枚举当前桶内的小值和之前最近那个非空桶内的最大值之间的差值即可……

代码:

class Solution {public:    int maxWidthOfVerticalArea(vector<vector<int>>& points) {        int mini = 1234567890, maxi = 0;        for (const auto& p : points) {            mini = min(mini, p[0]);            maxi = max(maxi, p[0]);        }        if (mini == maxi) return 0;                const long long n = points.size();        const int d = maxi - mini;        vector<vector<int>> v(n + 2);        for (const auto& p : points) {            int ind;             auto& arr = v[ind = (n + 1) * (p[0] - mini) / d];             if (arr.empty()) {                 arr = {p[0], p[0]};             } else {                 arr[0] = min(arr[0], p[0]);                 arr[1] = max(arr[1], p[0]);             }                      }         int r = 0;         for (int i = 1, last = v[0][1]; i < v.size(); ++i) {             if (!v[i].empty()) {                 r = max(r, v[i][0] - last);                 last = v[i][1];             }         }         return r;                 }};

bc671f6a7503241879ccb24033a58aec.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值