Skip to content

Commit 054930c

Browse files
author
o D
committed
more leetcode
1 parent 7b8ada7 commit 054930c

File tree

12 files changed

+2334
-16
lines changed

12 files changed

+2334
-16
lines changed

data-structure-and-algorithm/typescript/leetcode/package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,8 @@
2222
"gts": "^3.1.1",
2323
"typescript": "~4.7.0",
2424
"@types/node": "^14.11.2"
25+
},
26+
"engines": {
27+
"node": ">=18.12.1"
2528
}
26-
}
29+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/*
2+
2286. Booking Concert Tickets in Groups
3+
4+
A concert hall has n rows numbered from 0 to n - 1, each with m seats, numbered from 0 to m - 1. You need to design a ticketing system that can allocate seats in the following cases:
5+
6+
If a group of k spectators can sit together in a row.
7+
If every member of a group of k spectators can get a seat. They may or may not sit together.
8+
Note that the spectators are very picky. Hence:
9+
10+
They will book seats only if each member of their group can get a seat with row number less than or equal to maxRow. maxRow can vary from group to group.
11+
In case there are multiple rows to choose from, the row with the smallest number is chosen. If there are multiple seats to choose in the same row, the seat with the smallest number is chosen.
12+
Implement the BookMyShow class:
13+
14+
BookMyShow(int n, int m) Initializes the object with n as number of rows and m as number of seats per row.
15+
int[] gather(int k, int maxRow) Returns an array of length 2 denoting the row and seat number (respectively) of the first seat being allocated to the k members of the group, who must sit together. In other words, it returns the smallest possible r and c such that all [c, c + k - 1] seats are valid and empty in row r, and r <= maxRow. Returns [] in case it is not possible to allocate seats to the group.
16+
boolean scatter(int k, int maxRow) Returns true if all k members of the group can be allocated seats in rows 0 to maxRow, who may or may not sit together. If the seats can be allocated, it allocates k seats to the group with the smallest row numbers, and the smallest possible seat numbers in each row. Otherwise, returns false.
17+
18+
19+
Example 1:
20+
21+
Input
22+
["BookMyShow", "gather", "gather", "scatter", "scatter"]
23+
[[2, 5], [4, 0], [2, 0], [5, 1], [5, 1]]
24+
Output
25+
[null, [0, 0], [], true, false]
26+
27+
Explanation
28+
BookMyShow bms = new BookMyShow(2, 5); // There are 2 rows with 5 seats each
29+
bms.gather(4, 0); // return [0, 0]
30+
// The group books seats [0, 3] of row 0.
31+
bms.gather(2, 0); // return []
32+
// There is only 1 seat left in row 0,
33+
// so it is not possible to book 2 consecutive seats.
34+
bms.scatter(5, 1); // return True
35+
// The group books seat 4 of row 0 and seats [0, 3] of row 1.
36+
bms.scatter(5, 1); // return False
37+
// There is only one seat left in the hall.
38+
39+
40+
Constraints:
41+
42+
1 <= n <= 5 * 104
43+
1 <= m, k <= 109
44+
0 <= maxRow <= n - 1
45+
At most 5 * 104 calls in total will be made to gather and scatter.
46+
*/
47+
48+
import {BinaryIndexTree} from './data-structure/BinaryIndexTree';
49+
import {SegmentTree} from './data-structure/SegmentTree';
50+
51+
class BookMyShow {
52+
rows: number;
53+
seats: number;
54+
segTree: SegmentTree;
55+
biTree: BinaryIndexTree;
56+
57+
constructor(rows: number, seats: number) {
58+
this.rows = rows;
59+
this.seats = seats;
60+
this.segTree = new SegmentTree(Array(rows).fill(0));
61+
this.biTree = new BinaryIndexTree(Array(rows).fill(seats));
62+
}
63+
64+
gather(cnt: number, maxRow: number): [number, number] | [] {
65+
const idx = this.segTree.indexOf(0, this.seats - cnt);
66+
if (idx === -1 || idx > maxRow) {
67+
return [];
68+
}
69+
const min = this.segTree.min(idx, idx + 1);
70+
this.segTree.update(idx, min + cnt);
71+
this.biTree.updateDelta(idx, -cnt);
72+
return [idx, min];
73+
}
74+
75+
scatter(cnt: number, maxRow: number): boolean {
76+
const total = this.biTree.getSum(maxRow);
77+
if (total < cnt) {
78+
return false;
79+
}
80+
while (cnt > 0) {
81+
const idx = this.segTree.indexOf(0, this.seats - 1);
82+
if (idx === -1 || idx > maxRow) {
83+
break;
84+
}
85+
const min = this.segTree.min(idx, idx + 1);
86+
const use = Math.min(cnt, this.seats - min);
87+
cnt -= use;
88+
this.segTree.update(idx, min + use);
89+
this.biTree.updateDelta(idx, -use);
90+
}
91+
return true;
92+
}
93+
}
94+
95+
const bms = new BookMyShow(2, 5); // There are 2 rows with 5 seats each
96+
console.log(bms.gather(4, 0)); // return [0, 0]
97+
// The group books seats [0, 3] of row 0.
98+
console.log(bms.gather(2, 0)); // return []
99+
// There is only 1 seat left in row 0,
100+
// so it is not possible to book 2 consecutive seats.
101+
console.log(bms.scatter(5, 1)); // return True
102+
// The group books seat 4 of row 0 and seats [0, 3] of row 1.
103+
console.log(bms.scatter(5, 1)); // return False
104+
// There is only one seat left in the hall.
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
829. Consecutive Numbers Sum
3+
4+
Given an integer n, return the number of ways you can write n as the sum of consecutive positive integers.
5+
6+
7+
8+
Example 1:
9+
10+
Input: n = 5
11+
Output: 2
12+
Explanation: 5 = 2 + 3
13+
Example 2:
14+
15+
Input: n = 9
16+
Output: 3
17+
Explanation: 9 = 4 + 5 = 2 + 3 + 4
18+
Example 3:
19+
20+
Input: n = 15
21+
Output: 4
22+
Explanation: 15 = 8 + 7 = 4 + 5 + 6 = 1 + 2 + 3 + 4 + 5
23+
24+
25+
Constraints:
26+
27+
1 <= n <= 109
28+
*/
29+
30+
function consecutiveNumbersSum(target: number): number {
31+
let result = 0;
32+
let sum = 0;
33+
for (let i = 1; sum < target; ++i) {
34+
sum += i;
35+
if ((target - sum) % i === 0) {
36+
++result;
37+
}
38+
}
39+
return result;
40+
}

data-structure-and-algorithm/typescript/leetcode/src/data-structure/BinaryIndexTree.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,23 @@ export class BinaryIndexTree {
1111

1212
update(i: number, data: number): void {
1313
const diff = data - this.numList[i + 1];
14+
this.updateDelta(i, diff);
15+
}
16+
17+
updateDelta(i: number, delta: number): void {
1418
for (let j = i + 1; j < this.bitList.length; j += this.leastBit(j)) {
15-
this.bitList[j] += diff;
19+
this.bitList[j] += delta;
1620
}
17-
this.numList[i + 1] = data;
21+
this.numList[i + 1] = delta + this.numList[i + 1];
1822
}
1923

2024
sumRange(i: number, j: number): number {
21-
return this.getSum(j + 1) - this.getSum(i);
25+
return this.getSum(j) - this.getSum(i - 1);
2226
}
2327

2428
getSum(i: number): number {
2529
let result = 0;
26-
for (let j = i; j > 0; j -= this.leastBit(j)) {
30+
for (let j = i + 1; j > 0; j -= this.leastBit(j)) {
2731
result += this.bitList[j];
2832
}
2933
return result;
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
export class SegmentTree {
2+
minList: number[];
3+
maxList: number[];
4+
size: number;
5+
height: number;
6+
constructor(numList: number[]) {
7+
const {length} = numList;
8+
this.height = 2 ** Math.ceil(Math.log2(length));
9+
this.size = 2 * this.height;
10+
this.minList = Array(this.size).fill(Infinity);
11+
this.maxList = Array(this.size).fill(-Infinity);
12+
for (let i = 0; i < length; i++) {
13+
this.minList[this.height + i] = numList[i];
14+
this.maxList[this.height + i] = numList[i];
15+
}
16+
for (let i = this.height - 1; i >= 1; --i) {
17+
this.propagate(i);
18+
}
19+
}
20+
21+
update(idx: number, value: number): void {
22+
this.minList[this.height + idx] = value;
23+
this.maxList[this.height + idx] = value;
24+
for (let i = this.parent(this.height + idx); i >= 1; i = this.parent(i)) {
25+
this.propagate(i);
26+
}
27+
}
28+
29+
propagate(i: number): void {
30+
this.minList[i] = Math.min(
31+
this.minList[this.left(i)],
32+
this.minList[this.right(i)]
33+
);
34+
this.maxList[i] = Math.max(
35+
this.maxList[this.left(i)],
36+
this.maxList[this.right(i)]
37+
);
38+
}
39+
40+
min(i: number, j: number): number {
41+
let min = Infinity;
42+
for (
43+
let [x, y] = [i + this.height, j + this.height];
44+
x < y;
45+
x = this.parent(x), y = this.parent(y)
46+
) {
47+
if (x & 1) {
48+
min = Math.min(min, this.minList[x++]);
49+
}
50+
if (y & 1) {
51+
min = Math.min(min, this.minList[--y]);
52+
}
53+
}
54+
return min;
55+
}
56+
57+
max(i: number, j: number): number {
58+
let max = -Infinity;
59+
for (
60+
let [x, y] = [i + this.height, j + this.height];
61+
x < y;
62+
x = this.parent(x), y = this.parent(y)
63+
) {
64+
if (x & 1) {
65+
max = Math.max(max, this.maxList[x++]);
66+
}
67+
if (y & 1) {
68+
max = Math.max(max, this.maxList[--y]);
69+
}
70+
}
71+
return max;
72+
}
73+
74+
indexOf(i: number, value: number): number {
75+
if (i >= this.height) {
76+
return -1;
77+
}
78+
79+
for (let node = this.height + i; ; ) {
80+
if (this.minList[node] <= value) {
81+
if (node >= this.height) {
82+
return node - this.height;
83+
}
84+
node = this.left(node);
85+
} else {
86+
++node;
87+
if ((node & (node - 1)) === 0) {
88+
return -1;
89+
}
90+
if (node % 2 === 0) {
91+
node = this.parent(node);
92+
}
93+
}
94+
}
95+
}
96+
97+
parent(i: number): number {
98+
return i >> 1;
99+
}
100+
101+
left(i: number): number {
102+
return 2 * i;
103+
}
104+
105+
right(i: number): number {
106+
return 2 * i + 1;
107+
}
108+
109+
minTree(): number[] {
110+
return this.minList;
111+
}
112+
113+
maxTree(): number[] {
114+
return this.maxList;
115+
}
116+
}
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
/*
2+
399. Evaluate Division
3+
4+
You are given an array of variable pairs equations and an array of real numbers values, where equations[i] = [Ai, Bi] and values[i] represent the equation Ai / Bi = values[i]. Each Ai or Bi is a string that represents a single variable.
5+
6+
You are also given some queries, where queries[j] = [Cj, Dj] represents the jth query where you must find the answer for Cj / Dj = ?.
7+
8+
Return the answers to all queries. If a single answer cannot be determined, return -1.0.
9+
10+
Note: The input is always valid. You may assume that evaluating the queries will not result in division by zero and that there is no contradiction.
11+
12+
13+
14+
Example 1:
15+
16+
Input: equations = [["a","b"],["b","c"]], values = [2.0,3.0], queries = [["a","c"],["b","a"],["a","e"],["a","a"],["x","x"]]
17+
Output: [6.00000,0.50000,-1.00000,1.00000,-1.00000]
18+
Explanation:
19+
Given: a / b = 2.0, b / c = 3.0
20+
queries are: a / c = ?, b / a = ?, a / e = ?, a / a = ?, x / x = ?
21+
return: [6.0, 0.5, -1.0, 1.0, -1.0 ]
22+
Example 2:
23+
24+
Input: equations = [["a","b"],["b","c"],["bc","cd"]], values = [1.5,2.5,5.0], queries = [["a","c"],["c","b"],["bc","cd"],["cd","bc"]]
25+
Output: [3.75000,0.40000,5.00000,0.20000]
26+
Example 3:
27+
28+
Input: equations = [["a","b"]], values = [0.5], queries = [["a","b"],["b","a"],["a","c"],["x","y"]]
29+
Output: [0.50000,2.00000,-1.00000,-1.00000]
30+
31+
32+
Constraints:
33+
34+
1 <= equations.length <= 20
35+
equations[i].length == 2
36+
1 <= Ai.length, Bi.length <= 5
37+
values.length == equations.length
38+
0.0 < values[i] <= 20.0
39+
1 <= queries.length <= 20
40+
queries[i].length == 2
41+
1 <= Cj.length, Dj.length <= 5
42+
Ai, Bi, Cj, Dj consist of lower case English letters and digits.
43+
*/
44+
45+
import {Queue} from './data-structure/Queue';
46+
47+
function calcEquation(
48+
equations: string[][],
49+
values: number[],
50+
queries: string[][]
51+
): number[] {
52+
const map = new Map<string, [string, number][]>();
53+
for (let i = 0; i < equations.length; i++) {
54+
const [src, dst] = equations[i];
55+
if (!map.has(src)) {
56+
map.set(src, []);
57+
}
58+
if (!map.has(dst)) {
59+
map.set(dst, []);
60+
}
61+
map.get(src)!.push([dst, values[i]]);
62+
map.get(dst)!.push([src, 1 / values[i]]);
63+
}
64+
65+
const resultList: number[] = [];
66+
67+
for (const [src, dst] of queries) {
68+
const queue = new Queue<[string, number]>();
69+
const visited = new Set<string>();
70+
let result = -1;
71+
queue.push([src, 1]);
72+
visited.add(src);
73+
if (map.has(dst)) {
74+
while (!queue.isEmpty()) {
75+
const [node, value] = queue.pop();
76+
if (node === dst) {
77+
result = value;
78+
break;
79+
}
80+
if (!map.has(node)) {
81+
break;
82+
}
83+
for (const [nextNode, nextValue] of map.get(node)!) {
84+
if (!visited.has(nextNode)) {
85+
visited.add(nextNode);
86+
queue.push([nextNode, value * nextValue]);
87+
}
88+
}
89+
}
90+
}
91+
resultList.push(result);
92+
}
93+
return resultList;
94+
}

0 commit comments

Comments
 (0)