# 3143. Maximum Points Inside the Square

## Description

You are given a 2D array points and a string s where, points[i] represents the coordinates of point i, and s[i] represents the tag of point i.

A valid square is a square centered at the origin (0, 0), has edges parallel to the axes, and does not contain two points with the same tag.

Return the maximum number of points contained in a valid square.

Note:

• A point is considered to be inside the square if it lies on or within the square's boundaries.
• The side length of the square can be zero.

Example 1:

Input: points = [[2,2],[-1,-2],[-4,4],[-3,1],[3,-3]], s = "abdca"

Output: 2

Explanation:

The square of side length 4 covers two points points[0] and points[1].

Example 2:

Input: points = [[1,1],[-2,-2],[-2,2]], s = "abb"

Output: 1

Explanation:

The square of side length 2 covers one point, which is points[0].

Example 3:

Input: points = [[1,1],[-1,-1],[2,-2]], s = "ccd"

Output: 0

Explanation:

It's impossible to make any valid squares centered at the origin such that it covers only one point among points[0] and points[1].

Constraints:

• 1 <= s.length, points.length <= 105
• points[i].length == 2
• -109 <= points[i][0], points[i][1] <= 109
• s.length == points.length
• points consists of distinct coordinates.
• s consists only of lowercase English letters.

## Solutions

### Solution 1: Hash Table + Sorting

For a point $(x, y)$, we can map it to the first quadrant with the origin as the center, i.e., $(\max(|x|, |y|), \max(|x|, |y|))$. In this way, we can map all points to the first quadrant and then sort them according to the distance from the point to the origin.

We can use a hash table $g$ to store the distance from all points to the origin, and then sort them according to the distance. For each distance $d$, we put all points with a distance of $d$ together, and then traverse these points. If there are two points with the same label, then this square is illegal, and we directly return the answer. Otherwise, we add these points to the answer.

The time complexity is $O(n \times \log n)$, and the space complexity is $O(n)$, where $n$ is the number of points.

• 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));
}
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;
}
}

• 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;
}
};

• 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
ans += len(idx)
return ans


• 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
}

• 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;
}