Skip to content

Commit 590ac79

Browse files
authored
2025년 13주차 문제 풀이 (#38)
## 문제 풀이 목록 - [LeetCode 3169. Count Days Without Meetings](https://leetcode.com/problems/count-days-without-meetings) ✨ - [LeetCode 3394. Check if Grid can be Cut into Sections](https://leetcode.com/problems/check-if-grid-can-be-cut-into-sections) ✨ - [LeetCode 2033. Minimum Operations to Make a Uni-Value Grid](https://leetcode.com/problems/minimum-operations-to-make-a-uni-value-grid) ✨ - [LeetCode 2780. Minimum Index of a Valid Split](https://leetcode.com/problems/minimum-index-of-a-valid-split) ✨ - [LeetCode 2503. Maximum Number of Points From Grid Queries](https://leetcode.com/problems/maximum-number-of-points-from-grid-queries) ✨ - [LeetCode 2818. Apply Operations to Maximize Score](https://leetcode.com/problems/apply-operations-to-maximize-score) ✨ - [LeetCode 763. Partition Labels](https://leetcode.com/problems/partition-labels) ## 변경사항 - LeetCode 문제 풀이에 사용되는 의존성 추가 - [`@datastructures-js/deque`](https://github.com/datastructures-js/deque) - [`@datastructures-js/priority-queue`](https://github.com/datastructures-js/priority-queue) - [`@datastructures-js/queue`](https://github.com/datastructures-js/queue)
1 parent 1cea95d commit 590ac79

File tree

27 files changed

+1248
-2
lines changed

27 files changed

+1248
-2
lines changed

pnpm-lock.yaml

Lines changed: 31 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

solution/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515
},
1616
"prettier": "@algorithm/prettier-config",
1717
"dependencies": {
18-
"@algorithm/lib": "workspace:*"
18+
"@algorithm/lib": "workspace:*",
19+
"@datastructures-js/deque": "^1.0.5",
20+
"@datastructures-js/priority-queue": "^6.3.2",
21+
"@datastructures-js/queue": "^4.2.3"
1922
},
2023
"devDependencies": {
2124
"@algorithm/eslint-config": "workspace:*",
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import { minOperations } from './2033';
2+
3+
describe('LeetCode 2033', () => {
4+
test('Example 1', () => {
5+
expect(
6+
minOperations(
7+
[
8+
[2, 4],
9+
[6, 8],
10+
],
11+
2,
12+
),
13+
).toBe(4);
14+
});
15+
test('Example 2', () => {
16+
expect(
17+
minOperations(
18+
[
19+
[1, 5],
20+
[2, 3],
21+
],
22+
1,
23+
),
24+
).toBe(5);
25+
});
26+
test('Example 3', () => {
27+
expect(
28+
minOperations(
29+
[
30+
[1, 2],
31+
[3, 4],
32+
],
33+
2,
34+
),
35+
).toBe(-1);
36+
});
37+
test('Example 4', () => {
38+
expect(
39+
minOperations(
40+
[
41+
[454, 328, 160, 286, 664],
42+
[496, 538, 748, 244, 286],
43+
[34, 244, 454, 706, 790],
44+
[496, 538, 832, 958, 328],
45+
[370, 874, 370, 874, 286],
46+
],
47+
42,
48+
),
49+
).toBe(122);
50+
});
51+
});

solution/src/leetcode/2033/2033.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* 2033. Minimum Operations to Make a Uni-Value Grid
3+
* https://leetcode.com/problems/minimum-operations-to-make-a-uni-value-grid
4+
*/
5+
export function minOperations(grid: number[][], x: number): number {
6+
const values = grid.flat().sort((a, b) => a - b);
7+
const midValue = values[Math.floor(values.length / 2)];
8+
9+
let operations = 0;
10+
for (const value of values) {
11+
const diff = Math.abs(midValue - value);
12+
if (diff % x !== 0) {
13+
return -1;
14+
}
15+
operations += diff / x;
16+
}
17+
return operations;
18+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"id": "2033",
3+
"url": "https://leetcode.com/problems/minimum-operations-to-make-a-uni-value-grid",
4+
"title": "Minimum Operations to Make a Uni-Value Grid",
5+
"category": "Algorithms",
6+
"difficulty": "Medium",
7+
"tags": ["Array", "Math", "Sorting", "Matrix"]
8+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
import { maxPoints } from './2503';
2+
3+
describe('LeetCode 2503', () => {
4+
test('Example 1', () => {
5+
expect(
6+
maxPoints(
7+
[
8+
[1, 2, 3],
9+
[2, 5, 7],
10+
[3, 5, 1],
11+
],
12+
[5, 6, 2],
13+
),
14+
).toEqual([5, 8, 1]);
15+
});
16+
test('Example 2', () => {
17+
expect(
18+
maxPoints(
19+
[
20+
[5, 2, 1],
21+
[1, 1, 2],
22+
],
23+
[3],
24+
),
25+
).toEqual([0]);
26+
});
27+
test('Example 3', () => {
28+
expect(
29+
maxPoints(
30+
[
31+
[420766, 806051, 922751],
32+
[181527, 815280, 904568],
33+
[952102, 4037, 140319],
34+
[324081, 17907, 799523],
35+
[176688, 90257, 83661],
36+
[932477, 621193, 623068],
37+
[135839, 554701, 511427],
38+
[227575, 450848, 178065],
39+
[785644, 204668, 835141],
40+
[313774, 167359, 501496],
41+
[641317, 620688, 74989],
42+
[324499, 122376, 270369],
43+
[2121, 887154, 848859],
44+
[456704, 7763, 662087],
45+
[286827, 145349, 468865],
46+
[277137, 858176, 725551],
47+
[106131, 93684, 576512],
48+
[372563, 944355, 497187],
49+
[884187, 600892, 268120],
50+
[576578, 515031, 807686],
51+
],
52+
[352655, 586228, 169685, 541073, 584647, 413832, 576537, 616413],
53+
),
54+
).toEqual([0, 2, 0, 2, 2, 0, 2, 2]);
55+
});
56+
});

solution/src/leetcode/2503/2503.ts

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* 2503. Maximum Number of Points From Grid Queries
3+
* https://leetcode.com/problems/maximum-number-of-points-from-grid-queries
4+
*/
5+
export function maxPoints(grid: number[][], queries: number[]): number[] {
6+
const [m, n, k] = [grid.length, grid[0].length, queries.length];
7+
const directions = [
8+
[0, 1],
9+
[1, 0],
10+
[0, -1],
11+
[-1, 0],
12+
];
13+
const sortedQueries = queries.map((query, i) => [query, i]).sort((a, b) => a[0] - b[0]);
14+
const sortedCells = grid
15+
.flat()
16+
.map((value, i) => [value, Math.floor(i / n), i % n])
17+
.sort((a, b) => a[0] - b[0]);
18+
19+
const unionFind = new UnionFind(m * n);
20+
const result = new Array<number>(k).fill(0);
21+
22+
let cellIndex = 0;
23+
for (const [query, queryIndex] of sortedQueries) {
24+
while (cellIndex < m * n && sortedCells[cellIndex][0] < query) {
25+
const [_, y, x] = sortedCells[cellIndex];
26+
const cellId = y * n + x;
27+
28+
for (const [dy, dx] of directions) {
29+
const [ny, nx] = [y + dy, x + dx];
30+
if (0 <= ny && ny < m && 0 <= nx && nx < n && grid[ny][nx] < query) {
31+
unionFind.union(cellId, ny * n + nx);
32+
}
33+
}
34+
cellIndex += 1;
35+
}
36+
result[queryIndex] = query > grid[0][0] ? unionFind.getSize(0) : 0;
37+
}
38+
39+
return result;
40+
}
41+
42+
class UnionFind {
43+
private readonly parents: number[];
44+
private readonly sizes: number[];
45+
constructor(n: number) {
46+
this.parents = Array.from({ length: n }, (_, i) => i);
47+
this.sizes = new Array<number>(n).fill(1);
48+
}
49+
50+
find(x: number): number {
51+
if (this.parents[x] !== x) {
52+
this.parents[x] = this.find(this.parents[x]);
53+
}
54+
return this.parents[x];
55+
}
56+
57+
union(x: number, y: number): void {
58+
const parentX = this.find(x);
59+
const parentY = this.find(y);
60+
if (parentX === parentY) {
61+
return;
62+
}
63+
if (this.sizes[parentX] > this.sizes[parentY]) {
64+
this.parents[parentY] = parentX;
65+
this.sizes[parentX] += this.sizes[parentY];
66+
} else {
67+
this.parents[parentX] = parentY;
68+
this.sizes[parentY] += this.sizes[parentX];
69+
}
70+
}
71+
72+
getSize(x: number): number {
73+
return this.sizes[this.find(x)];
74+
}
75+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"id": "2503",
3+
"url": "https://leetcode.com/problems/maximum-number-of-points-from-grid-queries",
4+
"title": "Maximum Number of Points From Grid Queries",
5+
"category": "Algorithms",
6+
"difficulty": "Hard",
7+
"tags": [
8+
"Array",
9+
"Two Pointers",
10+
"Breadth-First Search",
11+
"Union Find",
12+
"Sorting",
13+
"Heap (Priority Queue)",
14+
"Matrix"
15+
]
16+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { minimumIndex } from './2780';
2+
3+
describe('LeetCode 2780', () => {
4+
test('Example 1', () => {
5+
expect(minimumIndex([1, 2, 2, 2])).toBe(2);
6+
});
7+
test('Example 2', () => {
8+
expect(minimumIndex([2, 1, 3, 1, 1, 1, 7, 1, 2, 1])).toBe(4);
9+
});
10+
test('Example 3', () => {
11+
expect(minimumIndex([3, 3, 3, 3, 7, 2, 2])).toBe(-1);
12+
});
13+
test('Example 4', () => {
14+
expect(minimumIndex([9, 5, 5, 1, 1, 1, 1, 8, 1])).toBe(-1);
15+
});
16+
});

solution/src/leetcode/2780/2780.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* 2780. Minimum Index of a Valid Split
3+
* https://leetcode.com/problems/minimum-index-of-a-valid-split
4+
*/
5+
export function minimumIndex(nums: number[]): number {
6+
const n = nums.length;
7+
const dominantElement = findDominantElement(nums);
8+
const totalCount = nums.reduce((count, num) => (num === dominantElement ? count + 1 : count), 0);
9+
10+
let leftCount = 0;
11+
for (let i = 0; i < n; i++) {
12+
if (nums[i] === dominantElement) {
13+
leftCount += 1;
14+
}
15+
16+
const rightCount = totalCount - leftCount;
17+
if (2 * leftCount > i + 1 && 2 * rightCount > n - i - 1) {
18+
return i;
19+
}
20+
}
21+
return -1;
22+
}
23+
24+
function findDominantElement(nums: number[]): number {
25+
let count = 0;
26+
let candidate = 0;
27+
for (const num of nums) {
28+
if (count === 0) {
29+
candidate = num;
30+
}
31+
count += candidate === num ? 1 : -1;
32+
}
33+
return candidate;
34+
}

0 commit comments

Comments
 (0)