|
| 1 | +## 题目地址(3027. 人员站位的方案数 II - 力扣(LeetCode)) |
| 2 | + |
| 3 | +https://leetcode.cn/problems/find-the-number-of-ways-to-place-people-ii/ |
| 4 | + |
| 5 | +## 题目描述 |
| 6 | + |
| 7 | +<p>给你一个 <code>n x 2</code> 的二维数组 <code>points</code> ,它表示二维平面上的一些点坐标,其中 <code>points[i] = [x<sub>i</sub>, y<sub>i</sub>]</code> 。</p> |
| 8 | + |
| 9 | +<p>我们定义 x 轴的正方向为 <strong>右</strong> (<strong>x 轴递增的方向</strong>),x 轴的负方向为 <strong>左</strong> (<strong>x 轴递减的方向</strong>)。类似的,我们定义 y 轴的正方向为 <strong>上</strong> (<strong>y 轴递增的方向</strong>),y 轴的负方向为 <strong>下</strong> (<strong>y 轴递减的方向</strong>)。</p> |
| 10 | + |
| 11 | +<p>你需要安排这 <code>n</code> 个人的站位,这 <code>n</code> 个人中包括 Alice 和 Bob 。你需要确保每个点处 <strong>恰好</strong> 有 <strong>一个</strong> 人。同时,Alice 想跟 Bob 单独玩耍,所以 Alice 会以 Bob<b> </b>的坐标为 <strong>左上角</strong> ,Bob 的坐标为 <strong>右下角</strong> 建立一个矩形的围栏(<strong>注意</strong>,围栏可能 <strong>不</strong> 包含任何区域,也就是说围栏可能是一条线段)。如果围栏的 <strong>内部</strong> 或者 <strong>边缘</strong> 上有任何其他人,Alice 都会难过。</p> |
| 12 | + |
| 13 | +<p>请你在确保 Alice <strong>不会</strong> 难过的前提下,返回 Alice 和 Bob 可以选择的 <strong>点对</strong> 数目。</p> |
| 14 | + |
| 15 | +<p><b>注意</b>,Alice 建立的围栏必须确保 Alice 的位置是矩形的左上角,Bob 的位置是矩形的右下角。比方说,以 <code>(1, 1)</code> ,<code>(1, 3)</code> ,<code>(3, 1)</code> 和 <code>(3, 3)</code> 为矩形的四个角,给定下图的两个输入,Alice 都不能建立围栏,原因如下:</p> |
| 16 | + |
| 17 | +<ul> |
| 18 | + <li>图一中,Alice 在 <code>(3, 3)</code> 且 Bob 在 <code>(1, 1)</code> ,Alice 的位置不是左上角且 Bob 的位置不是右下角。</li> |
| 19 | + <li>图二中,Alice 在 <code>(1, 3)</code> 且 Bob 在 <code>(1, 1)</code> ,Bob 的位置不是在围栏的右下角。</li> |
| 20 | +</ul> |
| 21 | +<img alt="" src="https://assets.leetcode.com/uploads/2024/01/04/example0alicebob-1.png" style="width: 750px; height: 308px; padding: 10px; background: rgb(255, 255, 255); border-radius: 0.5rem;"> |
| 22 | +<p> </p> |
| 23 | + |
| 24 | +<p><strong class="example">示例 1:</strong></p> |
| 25 | + |
| 26 | +<p><img alt="" src="https://assets.leetcode.com/uploads/2024/01/04/example1alicebob.png" style="width: 376px; height: 308px; padding: 10px; background: rgb(255, 255, 255); border-radius: 0.5rem;"></p> |
| 27 | + |
| 28 | +<pre><b>输入:</b>points = [[1,1],[2,2],[3,3]] |
| 29 | +<b>输出:</b>0 |
| 30 | +<strong>解释:</strong>没有办法可以让 Alice 的围栏以 Alice 的位置为左上角且 Bob 的位置为右下角。所以我们返回 0 。 |
| 31 | +</pre> |
| 32 | + |
| 33 | +<p><strong class="example">示例 2:</strong></p> |
| 34 | + |
| 35 | +<p><strong class="example"><a href="https://pic.leetcode.cn/1706880313-YelabI-example2.jpeg"><img alt="" src="https://pic.leetcode.cn/1708226715-CxjXKb-20240218-112338.jpeg" style="width: 900px; height: 248px;"></a></strong></p> |
| 36 | + |
| 37 | +<pre><b>输入:</b>points = [[6,2],[4,4],[2,6]] |
| 38 | +<b>输出:</b>2 |
| 39 | +<b>解释:</b>总共有 2 种方案安排 Alice 和 Bob 的位置,使得 Alice 不会难过: |
| 40 | +- Alice 站在 (4, 4) ,Bob 站在 (6, 2) 。 |
| 41 | +- Alice 站在 (2, 6) ,Bob 站在 (4, 4) 。 |
| 42 | +不能安排 Alice 站在 (2, 6) 且 Bob 站在 (6, 2) ,因为站在 (4, 4) 的人处于围栏内。 |
| 43 | +</pre> |
| 44 | + |
| 45 | +<p><strong class="example">示例 3:</strong></p> |
| 46 | + |
| 47 | +<p><strong class="example"><a href="https://pic.leetcode.cn/1706880311-mtPGYC-example3.jpeg"><img alt="" src="https://pic.leetcode.cn/1708226721-wTbEuK-20240218-112351.jpeg" style="width: 911px; height: 250px;"></a></strong></p> |
| 48 | + |
| 49 | +<pre><b>输入:</b>points = [[3,1],[1,3],[1,1]] |
| 50 | +<b>输出:</b>2 |
| 51 | +<b>解释:</b>总共有 2 种方案安排 Alice 和 Bob 的位置,使得 Alice 不会难过: |
| 52 | +- Alice 站在 (1, 1) ,Bob 站在 (3, 1) 。 |
| 53 | +- Alice 站在 (1, 3) ,Bob 站在 (1, 1) 。 |
| 54 | +不能安排 Alice 站在 (1, 3) 且 Bob 站在 (3, 1) ,因为站在 (1, 1) 的人处于围栏内。 |
| 55 | +注意围栏是可以不包含任何面积的,上图中第一和第二个围栏都是合法的。 |
| 56 | +</pre> |
| 57 | + |
| 58 | +<p> </p> |
| 59 | + |
| 60 | +<p><strong>提示:</strong></p> |
| 61 | + |
| 62 | +<ul> |
| 63 | + <li><code>2 <= n <= 1000</code></li> |
| 64 | + <li><code>points[i].length == 2</code></li> |
| 65 | + <li><code>-10<sup>9</sup> <= points[i][0], points[i][1] <= 10<sup>9</sup></code></li> |
| 66 | + <li><code>points[i]</code> 点对两两不同。</li> |
| 67 | +</ul> |
| 68 | + |
| 69 | +## 前置知识 |
| 70 | + |
| 71 | +- 暂无 |
| 72 | + |
| 73 | +## 公司 |
| 74 | + |
| 75 | +- 暂无 |
| 76 | + |
| 77 | +## 思路 |
| 78 | + |
| 79 | +为了方便确定谁是 alice,谁是 bob,首先我们按 x 正序排序。 |
| 80 | + |
| 81 | +令索引 i 是 alice (x1, y1),索引 j != i 的都**可能**作为 bob(x2, y2)。那什么样的 j 满足条件呢?需要满足: |
| 82 | + |
| 83 | +1. alice 纵坐标要大于等于 bob(横坐标由于排序已经保证了 alice 不大于 bob,满足题目要求) |
| 84 | + |
| 85 | +2. 中间的点纵坐标要么比两人都大,要么比两人都小。(即中间的点的纵坐标不能位于 alice 和 bob 中间) |
| 86 | + |
| 87 | +有一个特殊的 case: alice 和 bob 的横坐标相等,这种情况下如果 i 的纵坐标小于 j 的纵坐标,不一定是不满足题意的。因此 alice 和 bob 横坐标相等,因此我们可以将 alice 看成是 bob, bob 看成是 alice。经过这样的处理,就又满足题意了。 |
| 88 | + |
| 89 | +为了不做这种特殊处理,我们可以按照 x 正序排序的同时,对 x 相同的按照 y 逆序排序,这样就不可能出现横坐标相同,i 的纵坐标小于 j 的纵坐标的情况。另外这样在 i 确定的时候,i 前面的点也一定不是 j,因此只需要枚举 i 之后的点即可。 |
| 90 | + |
| 91 | +> 这样会错过一些情况吗?不会!因为这种 case 会在其他遍历的时候中枚举到。 |
| 92 | +
|
| 93 | +因此我们可以枚举 i 为 alice, j > i 为 bob。然后枚举 i 个 j 中间的点是否满足题意(不在 i 和 j 中间的不用看)。 |
| 94 | + |
| 95 | +接下来,我们看如何满足前面提到的两点。 |
| 96 | + |
| 97 | +对于第一点,只需比较 alice 和 bob 的 y 即可。 |
| 98 | + |
| 99 | +对于第二点,我们只需要记录最大的 y 即可。只要 y2 大于最大的 y 就行。如果 y2 <= max <= y1,那么就不行,否则可以。 其中 max 是 最可能在 alice 和 bob 之间的 y,这样不需要全部比较。这个所谓最可能得就是最大的 y。 |
| 100 | + |
| 101 | +大家可以结合图来理解。 |
| 102 | + |
| 103 | + |
| 104 | + |
| 105 | +如图,虚点是 i 和 j 中间的点。对于这些点只要纵坐标**不**在图上的两个横线之间就行。因此这些点的纵坐标**都**要么大于 y1,要么小于 y2。换句话说,这些点的纵坐标要么最小值大于 y1,要么最大值小于 y2。因此我们只需要记录最大的 y 即可。 |
| 106 | + |
| 107 | +## 关键点 |
| 108 | + |
| 109 | +- 排序 |
| 110 | + |
| 111 | +## 代码 |
| 112 | + |
| 113 | +- 语言支持:Python3 |
| 114 | + |
| 115 | +Python3 Code: |
| 116 | + |
| 117 | +```python |
| 118 | + |
| 119 | +class Solution: |
| 120 | + def numberOfPairs(self, points: List[List[int]]) -> int: |
| 121 | + points.sort(key=lambda p: (p[0], -p[1])) |
| 122 | + ans = 0 |
| 123 | + for i, (x1, y1) in enumerate(points): # point i |
| 124 | + max_y = -inf |
| 125 | + min_y = inf |
| 126 | + for (x2, y2) in points[i + 1:]: # point j |
| 127 | + if y1 < y2: continue # 确保条件1 |
| 128 | + if y2 > max_y or y1 < min_y: # 确保条件2 |
| 129 | + ans += 1 |
| 130 | + max_y = max(max_y, y2) |
| 131 | + min_y = min(min_y, y2) |
| 132 | + return ans |
| 133 | + |
| 134 | +``` |
| 135 | + |
| 136 | +**复杂度分析** |
| 137 | + |
| 138 | +令 n 为 points 长度。 |
| 139 | + |
| 140 | +- 时间复杂度:$O(nlogn)$ |
| 141 | +- 空间复杂度:$O(1)$ |
| 142 | + |
| 143 | +> 此题解由 [力扣刷题插件](https://leetcode-pp.github.io/leetcode-cheat/?tab=solution-template) 自动生成。 |
| 144 | +
|
| 145 | +力扣的小伙伴可以[关注我](https://leetcode-cn.com/u/fe-lucifer/),这样就会第一时间收到我的动态啦~ |
| 146 | + |
| 147 | +以上就是本文的全部内容了。大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 40K star 啦。大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。 |
| 148 | + |
| 149 | +关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。 |
| 150 | + |
| 151 | + |
0 commit comments