Skip to content

Commit 03375a6

Browse files
authored
2025년 16주차 문제 풀이 (#42)
## 문제 풀이 목록 - [LeetCode 1534. Count Good Triplets](https://leetcode.com/problems/count-good-triplets) - [LeetCode 2179. Count Good Triplets in an Array](https://leetcode.com/problems/count-good-triplets-in-an-array) ✨ - [LeetCode 2537. Count the Number of Good Subarrays](https://leetcode.com/problems/count-the-number-of-good-subarrays) ✨ - [LeetCode 2176. Count Equal and Divisible Pairs in an Array](https://leetcode.com/problems/count-equal-and-divisible-pairs-in-an-array) - [LeetCode 38. Count and Say](https://leetcode.com/problems/count-and-say) - [LeetCode 2563. Count the Number of Fair Pairs](https://leetcode.com/problems/count-the-number-of-fair-pairs) - [LeetCode 781. Rabbits in Forest](https://leetcode.com/problems/rabbits-in-forest) ✨
1 parent d2d512f commit 03375a6

File tree

22 files changed

+1139
-476
lines changed

22 files changed

+1139
-476
lines changed

solution/README.md

Lines changed: 378 additions & 375 deletions
Large diffs are not rendered by default.

solution/src/leetcode/0038/0038.test.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@ import { countAndSay } from './0038';
22

33
describe('LeetCode 0038', () => {
44
test('Example 1', () => {
5-
expect(countAndSay(1)).toBe('1');
6-
});
7-
test('Example 2', () => {
85
expect(countAndSay(4)).toBe('1211');
96
});
10-
test('Example 3', () => {
11-
expect(countAndSay(5)).toBe('111221');
7+
test('Example 2', () => {
8+
expect(countAndSay(1)).toBe('1');
129
});
1310
});

solution/src/leetcode/0038/0038.ts

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,24 @@
33
* https://leetcode.com/problems/count-and-say
44
*/
55
export function countAndSay(n: number): string {
6-
const count = (s: string) => {
7-
let result = '';
6+
let current = '1';
7+
for (let i = 0; i < n - 1; i++) {
8+
current = runLengthEncoding(current);
9+
}
10+
return current;
11+
}
812

9-
let num = '';
10-
let count = 0;
11-
for (const char of s) {
12-
if (num === char) {
13-
count += 1;
14-
continue;
15-
}
16-
if (0 < count) {
17-
result += `${count.toString()}${num.toString()}`;
18-
}
19-
num = char;
13+
function runLengthEncoding(s: string): string {
14+
let result = '';
15+
let count = 1;
16+
for (let i = 1; i < s.length; i++) {
17+
if (s[i - 1] === s[i]) {
18+
count += 1;
19+
} else {
20+
result += `${count.toString()}${s[i - 1]}`;
2021
count = 1;
2122
}
22-
result += `${count.toString()}${num.toString()}`;
23-
return result;
24-
};
25-
26-
let answer = '1';
27-
for (let i = 2; i <= n; i++) {
28-
answer = count(answer);
2923
}
30-
return answer;
24+
result += `${count.toString()}${s[s.length - 1]}`;
25+
return result;
3126
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { numRabbits } from './0781';
2+
3+
describe('LeetCode 0781', () => {
4+
test('Example 1', () => {
5+
expect(numRabbits([1, 1, 2])).toBe(5);
6+
});
7+
test('Example 2', () => {
8+
expect(numRabbits([10, 10, 10])).toBe(11);
9+
});
10+
});

solution/src/leetcode/0781/0781.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* 781. Rabbits in Forest
3+
* https://leetcode.com/problems/rabbits-in-forest
4+
*/
5+
export function numRabbits(answers: number[]): number {
6+
const counter = new Map<number, number>();
7+
for (const answer of answers) {
8+
counter.set(answer, (counter.get(answer) ?? 0) + 1);
9+
}
10+
11+
let result = 0;
12+
for (const [answer, count] of counter) {
13+
const groupCount = Math.ceil(count / (answer + 1));
14+
result += groupCount * (answer + 1);
15+
}
16+
return result;
17+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
{
2+
"id": "781",
3+
"url": "https://leetcode.com/problems/rabbits-in-forest",
4+
"title": "Rabbits in Forest",
5+
"category": "Algorithms",
6+
"difficulty": "Medium",
7+
"tags": ["Array", "Hash Table", "Math", "Greedy"]
8+
}

solution/src/leetcode/1534/1534.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,21 @@
33
* https://leetcode.com/problems/count-good-triplets
44
*/
55
export function countGoodTriplets(arr: number[], a: number, b: number, c: number): number {
6-
const diff = (i: number, j: number) => Math.abs(arr[i] - arr[j]);
76
const n = arr.length;
87

98
let answer = 0;
109
for (let i = 0; i < n; i++) {
1110
for (let j = i + 1; j < n; j++) {
12-
if (diff(i, j) > a) {
11+
if (Math.abs(arr[i] - arr[j]) > a) {
1312
continue;
1413
}
14+
1515
for (let k = j + 1; k < n; k++) {
16-
if (diff(j, k) <= b && diff(i, k) <= c) {
16+
if (Math.abs(arr[j] - arr[k]) <= b && Math.abs(arr[i] - arr[k]) <= c) {
1717
answer += 1;
1818
}
1919
}
2020
}
2121
}
22-
2322
return answer;
2423
}

solution/src/leetcode/2176/2176.ts

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,29 @@
33
* https://leetcode.com/problems/count-equal-and-divisible-pairs-in-an-array
44
*/
55
export function countPairs(nums: number[], k: number): number {
6-
const indicesByValue = new Map<number, number[]>();
7-
8-
let answer = 0;
6+
const indicesByNum = new Map<number, number[]>();
97
nums.forEach((num, i) => {
10-
const indices = indicesByValue.get(num) ?? [];
11-
if (indices.length === 0) {
12-
indicesByValue.set(num, [i]);
13-
return;
14-
}
15-
16-
for (const j of indices) {
17-
if ((i * j) % k === 0) {
18-
answer += 1;
19-
}
20-
}
8+
const indices = indicesByNum.get(num) ?? [];
219
indices.push(i);
10+
indicesByNum.set(num, indices);
2211
});
2312

13+
let answer = 0;
14+
for (const indices of indicesByNum.values()) {
15+
const gcdCount = new Map<number, number>();
16+
for (const i of indices) {
17+
const gcdI = gcd(i, k);
18+
for (const [gcdJ, count] of gcdCount) {
19+
if ((gcdI * gcdJ) % k === 0) {
20+
answer += count;
21+
}
22+
}
23+
gcdCount.set(gcdI, (gcdCount.get(gcdI) ?? 0) + 1);
24+
}
25+
}
2426
return answer;
2527
}
28+
29+
function gcd(a: number, b: number): number {
30+
return b === 0 ? a : gcd(b, a % b);
31+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { goodTriplets } from './2179';
2+
3+
describe('LeetCode 2179', () => {
4+
test('Example 1', () => {
5+
expect(goodTriplets([2, 0, 1, 3], [0, 1, 2, 3])).toBe(1);
6+
});
7+
test('Example 2', () => {
8+
expect(goodTriplets([4, 0, 1, 3, 2], [4, 1, 0, 2, 3])).toBe(4);
9+
});
10+
});

solution/src/leetcode/2179/2179.ts

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* 2179. Count Good Triplets in an Array
3+
* https://leetcode.com/problems/count-good-triplets-in-an-array
4+
*/
5+
export function goodTriplets(nums1: number[], nums2: number[]): number {
6+
const n = nums1.length;
7+
const pos2 = new Array<number>(n).fill(-1);
8+
const indexMapping = new Array<number>(n).fill(-1);
9+
nums2.forEach((num2, i) => {
10+
pos2[num2] = i;
11+
});
12+
nums1.forEach((num1, i) => {
13+
indexMapping[pos2[num1]] = i;
14+
});
15+
16+
const tree = new BinaryIndexedTree(n);
17+
let answer = 0;
18+
for (let value = 0; value < n; value++) {
19+
const pos = indexMapping[value];
20+
21+
const left = tree.query(pos);
22+
tree.update(pos, 1);
23+
const right = n - 1 - pos - (value - left);
24+
answer += left * right;
25+
}
26+
return answer;
27+
}
28+
29+
class BinaryIndexedTree {
30+
readonly size: number;
31+
private readonly tree: number[];
32+
33+
constructor(size: number) {
34+
this.size = size;
35+
this.tree = new Array<number>(this.size + 1).fill(0);
36+
}
37+
38+
update(index: number, delta: number): void {
39+
let currentIndex = index + 1;
40+
while (currentIndex <= this.size) {
41+
this.tree[currentIndex] += delta;
42+
currentIndex += currentIndex & -currentIndex;
43+
}
44+
}
45+
46+
query(index: number): number {
47+
let result = 0;
48+
let currentIndex = index + 1;
49+
while (currentIndex > 0) {
50+
result += this.tree[currentIndex];
51+
currentIndex -= currentIndex & -currentIndex;
52+
}
53+
return result;
54+
}
55+
}

0 commit comments

Comments
 (0)