题目描述
给你一个二维数组 points
和一个字符串 s
,其中 points[i]
表示第 i
个点的坐标,s[i]
表示第 i
个点的 标签 。
如果一个正方形的中心在 (0, 0)
,所有边都平行于坐标轴,且正方形内 不 存在标签相同的两个点,那么我们称这个正方形是 合法 的。
请你返回 合法 正方形中可以包含的 最多 点数。
注意:
- 如果一个点位于正方形的边上或者在边以内,则认为该点位于正方形内。
- 正方形的边长可以为零。
示例 1:
输入:points = [[2,2],[-1,-2],[-4,4],[-3,1],[3,-3]], s = "abdca"
输出:2
解释:
边长为 4 的正方形包含两个点 points[0]
和 points[1]
。
示例 2:
输入:points = [[1,1],[-2,-2],[-2,2]], s = "abb"
输出:1
解释:
边长为 2 的正方形包含 1 个点 points[0]
。
示例 3:
输入:points = [[1,1],[-1,-1],[2,-2]], s = "ccd"
输出:0
解释:
任何正方形都无法只包含 points[0]
和 points[1]
中的一个点,所以合法正方形中都不包含任何点。
提示:
1 <= s.length, points.length <= 105
points[i].length == 2
-109 <= points[i][0], points[i][1] <= 109
s.length == points.length
points
中的点坐标互不相同。
s
只包含小写英文字母。
解法
方法一:哈希表 + 排序
对于一个点 $(x, y)$,我们可以将其映射到以原点为中心的第一象限,即 $(\max(|x|, |y|), \max(|x|, |y|))$。这样,我们就可以将所有的点映射到第一象限,然后按照点到原点的距离进行排序。
我们可以使用哈希表 $g$ 来存储所有点到原点的距离,然后按照距离进行排序。对于每个距离 $d$,我们将所有距离为 $d$ 的点放在一起,然后遍历这些点,如果有两个点的标签相同,那么这个正方形是不合法的,直接返回答案。否则,我们将这些点加入到答案中。
时间复杂度 $O(n \times \log n)$,空间复杂度 $O(n)$。其中 $n$ 是点的数量。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | class Solution:
def maxPointsInsideSquare(self, points: List[List[int]], s: str) -> int:
g = defaultdict(list)
for i, (x, y) in enumerate(points):
g[max(abs(x), abs(y))].append(i)
vis = set()
ans = 0
for d in sorted(g):
idx = g[d]
for i in idx:
if s[i] in vis:
return ans
vis.add(s[i])
ans += len(idx)
return ans
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 | class Solution {
public int maxPointsInsideSquare(int[][] points, String s) {
TreeMap<Integer, List<Integer>> g = new TreeMap<>();
for (int i = 0; i < points.length; ++i) {
int x = points[i][0], y = points[i][1];
int key = Math.max(Math.abs(x), Math.abs(y));
g.computeIfAbsent(key, k -> new ArrayList<>()).add(i);
}
boolean[] vis = new boolean[26];
int ans = 0;
for (var idx : g.values()) {
for (int i : idx) {
int j = s.charAt(i) - 'a';
if (vis[j]) {
return ans;
}
vis[j] = true;
}
ans += idx.size();
}
return ans;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 | class Solution {
public:
int maxPointsInsideSquare(vector<vector<int>>& points, string s) {
map<int, vector<int>> g;
for (int i = 0; i < points.size(); ++i) {
auto& p = points[i];
int key = max(abs(p[0]), abs(p[1]));
g[key].push_back(i);
}
bool vis[26]{};
int ans = 0;
for (auto& [_, idx] : g) {
for (int i : idx) {
int j = s[i] - 'a';
if (vis[j]) {
return ans;
}
vis[j] = true;
}
ans += idx.size();
}
return ans;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | func maxPointsInsideSquare(points [][]int, s string) (ans int) {
g := map[int][]int{}
for i, p := range points {
key := max(p[0], -p[0], p[1], -p[1])
g[key] = append(g[key], i)
}
vis := [26]bool{}
keys := []int{}
for k := range g {
keys = append(keys, k)
}
sort.Ints(keys)
for _, k := range keys {
idx := g[k]
for _, i := range idx {
j := s[i] - 'a'
if vis[j] {
return
}
vis[j] = true
}
ans += len(idx)
}
return
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 | function maxPointsInsideSquare(points: number[][], s: string): number {
const n = points.length;
const g: Map<number, number[]> = new Map();
for (let i = 0; i < n; ++i) {
const [x, y] = points[i];
const key = Math.max(Math.abs(x), Math.abs(y));
if (!g.has(key)) {
g.set(key, []);
}
g.get(key)!.push(i);
}
const keys = Array.from(g.keys()).sort((a, b) => a - b);
const vis: boolean[] = Array(26).fill(false);
let ans = 0;
for (const key of keys) {
const idx = g.get(key)!;
for (const i of idx) {
const j = s.charCodeAt(i) - 'a'.charCodeAt(0);
if (vis[j]) {
return ans;
}
vis[j] = true;
}
ans += idx.length;
}
return ans;
}
|