Skip to content

Commit c1384c6

Browse files
committed
Add solution #631
1 parent 5e26512 commit c1384c6

File tree

2 files changed

+142
-0
lines changed

2 files changed

+142
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,7 @@
586586
628|[Maximum Product of Three Numbers](./solutions/0628-maximum-product-of-three-numbers.js)|Easy|
587587
629|[K Inverse Pairs Array](./solutions/0629-k-inverse-pairs-array.js)|Hard|
588588
630|[Course Schedule III](./solutions/0630-course-schedule-iii.js)|Hard|
589+
631|[Design Excel Sum Formula](./solutions/0631-design-excel-sum-formula.js)|Hard|
589590
632|[Smallest Range Covering Elements from K Lists](./solutions/0632-smallest-range-covering-elements-from-k-lists.js)|Hard|
590591
633|[Sum of Square Numbers](./solutions/0633-sum-of-square-numbers.js)|Medium|
591592
636|[Exclusive Time of Functions](./solutions/0636-exclusive-time-of-functions.js)|Medium|
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/**
2+
* 631. Design Excel Sum Formula
3+
* https://leetcode.com/problems/design-excel-sum-formula/
4+
* Difficulty: Hard
5+
*
6+
* Design the basic function of Excel and implement the function of the sum formula.
7+
*
8+
* Implement the Excel class:
9+
* - Excel(int height, char width) Initializes the object with the height and the width
10+
* of the sheet. The sheet is an integer matrix mat of size height x width with the row
11+
* index in the range [1, height] and the column index in the range ['A', width]. All the
12+
* values should be zero initially.
13+
* - void set(int row, char column, int val) Changes the value at mat[row][column] to be val.
14+
* - int get(int row, char column) Returns the value at mat[row][column].
15+
* - int sum(int row, char column, List<String> numbers) Sets the value at mat[row][column] to
16+
* be the sum of cells represented by numbers and returns the value at mat[row][column].
17+
* This sum formula should exist until this cell is overlapped by another value or another
18+
* sum formula. numbers[i] could be on the format:
19+
* - "ColRow" that represents a single cell.
20+
* - For example, "F7" represents the cell mat[7]['F'].
21+
* - "ColRow1:ColRow2" that represents a range of cells. The range will always be a rectangle
22+
* where "ColRow1" represent the position of the top-left cell, and "ColRow2" represents the
23+
* position of the bottom-right cell.
24+
* - For example, "B3:F7" represents the cells mat[i][j] for 3 <= i <= 7 and 'B' <= j <= 'F'.
25+
*
26+
* Note: You could assume that there will not be any circular sum reference.
27+
*
28+
* For example, mat[1]['A'] == sum(1, "B") and mat[1]['B'] == sum(1, "A").
29+
*/
30+
31+
/**
32+
* @param {number} height
33+
* @param {character} width
34+
*/
35+
var Excel = function(height, width) {
36+
this.height = height;
37+
this.width = width.charCodeAt(0) - 64;
38+
this.matrix = new Array(height).fill().map(() => new Array(this.width).fill(0));
39+
this.formulas = new Map();
40+
this.dependencies = new Map();
41+
};
42+
43+
/**
44+
* @param {number} row
45+
* @param {character} column
46+
* @param {number} val
47+
* @return {void}
48+
*/
49+
Excel.prototype.set = function(row, column, val) {
50+
const col = column.charCodeAt(0) - 65;
51+
const key = `${row}:${column}`;
52+
this.matrix[row - 1][col] = val;
53+
if (this.formulas.has(key)) {
54+
this.formulas.delete(key);
55+
this.dependencies.get(key)?.delete(key);
56+
}
57+
this.updateDependents(row, column);
58+
};
59+
60+
/**
61+
* @param {number} row
62+
* @param {character} column
63+
* @return {number}
64+
*/
65+
Excel.prototype.get = function(row, column) {
66+
const col = column.charCodeAt(0) - 65;
67+
return this.matrix[row - 1][col];
68+
};
69+
70+
/**
71+
* @param {number} row
72+
* @param {character} column
73+
* @param {string[]} numbers
74+
* @return {number}
75+
*/
76+
Excel.prototype.sum = function(row, column, numbers) {
77+
const col = column.charCodeAt(0) - 65;
78+
const cellKey = `${row}:${column}`;
79+
const cells = [];
80+
81+
for (const num of numbers) {
82+
if (num.includes(':')) {
83+
const [start, end] = num.split(':');
84+
const startCol = start[0].charCodeAt(0) - 65;
85+
const startRow = parseInt(start.slice(1)) - 1;
86+
const endCol = end[0].charCodeAt(0) - 65;
87+
const endRow = parseInt(end.slice(1)) - 1;
88+
89+
for (let r = startRow; r <= endRow; r++) {
90+
for (let c = startCol; c <= endCol; c++) {
91+
cells.push([r, c]);
92+
}
93+
}
94+
} else {
95+
const c = num[0].charCodeAt(0) - 65;
96+
const r = parseInt(num.slice(1)) - 1;
97+
cells.push([r, c]);
98+
}
99+
}
100+
101+
if (this.formulas.has(cellKey)) {
102+
for (const [r, c] of this.formulas.get(cellKey)) {
103+
const depKey = `${r + 1}:${String.fromCharCode(c + 65)}`;
104+
this.dependencies.get(depKey)?.delete(cellKey);
105+
}
106+
}
107+
108+
this.formulas.set(cellKey, cells);
109+
for (const [r, c] of cells) {
110+
const depKey = `${r + 1}:${String.fromCharCode(c + 65)}`;
111+
if (!this.dependencies.has(depKey)) {
112+
this.dependencies.set(depKey, new Set());
113+
}
114+
this.dependencies.get(depKey).add(cellKey);
115+
}
116+
117+
const total = this.calculateSum(cells);
118+
this.matrix[row - 1][col] = total;
119+
this.updateDependents(row, column);
120+
return total;
121+
};
122+
123+
Excel.prototype.calculateSum = function(cells) {
124+
return cells.reduce((sum, [r, c]) => sum + this.matrix[r][c], 0);
125+
};
126+
127+
Excel.prototype.updateDependents = function(row, column) {
128+
const key = `${row}:${column}`;
129+
if (!this.dependencies.has(key)) return;
130+
131+
for (const depKey of this.dependencies.get(key)) {
132+
const [depRow, depCol] = depKey.split(':');
133+
const col = depCol.charCodeAt(0) - 65;
134+
const cells = this.formulas.get(depKey);
135+
if (cells) {
136+
const newSum = this.calculateSum(cells);
137+
this.matrix[parseInt(depRow) - 1][col] = newSum;
138+
this.updateDependents(parseInt(depRow), depCol);
139+
}
140+
}
141+
};

0 commit comments

Comments
 (0)