Skip to content

Commit 128155d

Browse files
committed
풀이: 릿코드.1878.Get Biggest Three Rhombus Sums in a Grid
?: prefix sum & heap을 이용해 풀이
1 parent 5fbe439 commit 128155d

3 files changed

Lines changed: 283 additions & 0 deletions

File tree

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# 1878. Get Biggest Three Rhombus Sums in a Grid
2+
3+
[링크](https://leetcode.com/problems/get-biggest-three-rhombus-sums-in-a-grid/description/)
4+
5+
| 난이도 |
6+
| :----: |
7+
| Medium |
8+
9+
## 설계
10+
11+
### 시간 복잡도
12+
13+
2차원 배열의 행의 갯수를 R, 열의 갯수를 C라 하자.
14+
15+
prefix sum을 이용해 특정 좌표에서의 마름모의 길이를 빠르게 구할 수 있다.
16+
17+
이 경우 prefix sum을 생성하는데 O(RC \* min(R, C))의 시간이 소요된다.
18+
19+
이후 각 좌표를 순회하며 정답을 구하는데 O(RC \* min(R, C))의 시간이 소요된다.
20+
21+
### 공간 복잡도
22+
23+
대각선 방향의 prefix sum을 사용할 경우 O(RC)의 공간 복잡도를 사용한다.
24+
25+
각 좌표마다 마름모 상단, 하단에 대한 길이에 대해 prefix sum을 저장할 경우 O(RC \* min(R, C))의 공간 복잡도를 사용한다.
26+
27+
### prefix sum & heap
28+
29+
| 내 코드 (ms) | 시간 복잡도 | 공간 복잡도 |
30+
| :----------: | :----------------: | :----------------: |
31+
| 255 | O(RC \* min(R, C)) | O(RC \* min(R, C)) |
32+
33+
2개의 prefix sum을 생성한다.
34+
35+
- `topDp[y][x][l]` : (y, x)를 시작으로 하는 마름모의 상단 부분의 길이가 l인 경우의 합
36+
- `downDp[y][x][l]` : (y, x)를 시작으로 하는 마름모의 하단 부분의 길이가 l인 경우의 합
37+
38+
이를 미리 구한 뒤 각 좌표마다 마름모의 길이를 늘려가며 정답을 구한다.
39+
40+
이 때 정답의 값이 유니크하며 가장 큰 3개를 구해야 하므로 힙과 unordered_set을 이용한다.
41+
42+
```cpp
43+
vector<int> getBiggestThree(vector<vector<int>>& grid) {
44+
int rows = grid.size(), cols = grid[0].size();
45+
46+
vector<vector<vector<int>>> topDp(
47+
rows, vector<vector<int>>(cols, vector<int>(51, INT_MIN)));
48+
vector<vector<vector<int>>> downDp(
49+
rows, vector<vector<int>>(cols, vector<int>(51, INT_MIN)));
50+
51+
for (int y = 0; y < rows; y++) {
52+
for (int x = 0; x < cols; x++) {
53+
topDp[y][x][0] = 0;
54+
topDp[y][x][1] = grid[y][x];
55+
for (int l = 2; l <= 50; l++) {
56+
int diff = l - 1;
57+
58+
if (x - diff < 0 || x + diff >= cols) break;
59+
if (y + diff >= rows) break;
60+
topDp[y][x][l] = topDp[y][x][l - 1] + grid[y + diff][x + diff] +
61+
grid[y + diff][x - diff];
62+
}
63+
64+
downDp[y][x][0] = 0;
65+
downDp[y][x][1] = grid[y][x];
66+
for (int l = 2; l <= 50; l++) {
67+
int diff = l - 1;
68+
69+
if (x - diff < 0 || x + diff >= cols) break;
70+
if (y - diff < 0) break;
71+
downDp[y][x][l] = downDp[y][x][l - 1] + grid[y - diff][x + diff] +
72+
grid[y - diff][x - diff];
73+
}
74+
}
75+
}
76+
77+
priority_queue<int, vector<int>, greater<int>> pq;
78+
unordered_set<int> visited;
79+
function<void(int)> add = [&](int sum) {
80+
if (visited.count(sum) == 0) {
81+
visited.insert(sum);
82+
pq.push(sum);
83+
if (pq.size() > 3) {
84+
pq.pop();
85+
}
86+
}
87+
};
88+
for (int y = 0; y < rows; y++) {
89+
for (int x = 0; x < cols; x++) {
90+
for (int l = 1; l <= 50; l++) {
91+
int diff = l - 1;
92+
if (y + 2 * diff >= rows) break;
93+
if (topDp[y][x][l] == INT_MIN ||
94+
downDp[y + 2 * diff][x][l - 1] == INT_MIN)
95+
break;
96+
int cur = topDp[y][x][l] + downDp[y + 2 * diff][x][l - 1];
97+
98+
add(cur);
99+
}
100+
}
101+
}
102+
103+
vector<int> answer;
104+
while (!pq.empty()) {
105+
answer.push_back(pq.top());
106+
pq.pop();
107+
}
108+
reverse(answer.begin(), answer.end());
109+
return answer;
110+
}
111+
```
112+
113+
## 고생한 점
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
#include <algorithm>
2+
#include <climits>
3+
#include <cmath>
4+
#include <cstring>
5+
#include <functional>
6+
#include <iostream>
7+
#include <map>
8+
#include <numeric>
9+
#include <queue>
10+
#include <set>
11+
#include <stack>
12+
#include <string>
13+
#include <unordered_map>
14+
#include <unordered_set>
15+
#include <vector>
16+
17+
using namespace std;
18+
19+
// prefix sum & heap
20+
// time : O(RC \* min(R, C))
21+
// space : O(RC)
22+
class Solution {
23+
public:
24+
vector<int> getBiggestThree(vector<vector<int>>& grid) {
25+
int rows = grid.size(), cols = grid[0].size();
26+
vector<vector<int>> rightDp(rows + 1, vector<int>(cols + 2));
27+
vector<vector<int>> leftDp(rows + 1, vector<int>(cols + 2));
28+
for (int y = 1; y <= rows; y++) {
29+
for (int x = 1; x <= cols; x++) {
30+
rightDp[y][x] = rightDp[y - 1][x - 1] + grid[y - 1][x - 1];
31+
leftDp[y][x] = leftDp[y - 1][x + 1] + grid[y - 1][x - 1];
32+
}
33+
}
34+
35+
unordered_set<int> visited;
36+
priority_queue<int, vector<int>, greater<int>> pq;
37+
38+
function<void(int)> add = [&](int sum) {
39+
if (visited.count(sum) == 0) {
40+
visited.insert(sum);
41+
pq.push(sum);
42+
if (pq.size() > 3) {
43+
visited.erase(pq.top());
44+
pq.pop();
45+
}
46+
}
47+
};
48+
49+
for (int y = 0; y < rows; ++y) {
50+
for (int x = 0; x < cols; ++x) {
51+
add(grid[y][x]);
52+
53+
for (int yy = y + 2; yy < rows; yy += 2) {
54+
int uy = y, ux = x;
55+
int dy = yy, dx = x;
56+
int ly = (y + yy) / 2, lx = x - (yy - y) / 2;
57+
int ry = (y + yy) / 2, rx = x + (yy - y) / 2;
58+
59+
if (lx < 0 || rx >= cols) break;
60+
61+
int topLeft = leftDp[ly + 1][lx + 1] - leftDp[uy][ux + 2];
62+
int topRight = rightDp[ry + 1][rx + 1] - rightDp[uy][ux];
63+
int bottomRight = rightDp[dy + 1][dx + 1] - rightDp[ly][lx];
64+
int bottomLeft = leftDp[dy + 1][dx + 1] - leftDp[ry][rx + 2];
65+
66+
int duplicated =
67+
grid[uy][ux] + grid[dy][dx] + grid[ly][lx] + grid[ry][rx];
68+
69+
int sum = topLeft + topRight + bottomRight + bottomLeft - duplicated;
70+
71+
add(sum);
72+
}
73+
}
74+
}
75+
vector<int> answer;
76+
while (!pq.empty()) {
77+
answer.push_back(pq.top());
78+
pq.pop();
79+
}
80+
reverse(answer.begin(), answer.end());
81+
return answer;
82+
}
83+
};
84+
85+
// prefix sum & heap
86+
// time : O(RC \* min(R, C))
87+
// space : O(RC \* min(R, C))
88+
class Solution {
89+
public:
90+
vector<int> getBiggestThree(vector<vector<int>>& grid) {
91+
int rows = grid.size(), cols = grid[0].size();
92+
93+
vector<vector<vector<int>>> topDp(
94+
rows, vector<vector<int>>(cols, vector<int>(51, INT_MIN)));
95+
vector<vector<vector<int>>> downDp(
96+
rows, vector<vector<int>>(cols, vector<int>(51, INT_MIN)));
97+
98+
for (int y = 0; y < rows; y++) {
99+
for (int x = 0; x < cols; x++) {
100+
topDp[y][x][0] = 0;
101+
topDp[y][x][1] = grid[y][x];
102+
for (int l = 2; l <= 50; l++) {
103+
int diff = l - 1;
104+
105+
if (x - diff < 0 || x + diff >= cols) break;
106+
if (y + diff >= rows) break;
107+
topDp[y][x][l] = topDp[y][x][l - 1] + grid[y + diff][x + diff] +
108+
grid[y + diff][x - diff];
109+
}
110+
111+
downDp[y][x][0] = 0;
112+
downDp[y][x][1] = grid[y][x];
113+
for (int l = 2; l <= 50; l++) {
114+
int diff = l - 1;
115+
116+
if (x - diff < 0 || x + diff >= cols) break;
117+
if (y - diff < 0) break;
118+
downDp[y][x][l] = downDp[y][x][l - 1] + grid[y - diff][x + diff] +
119+
grid[y - diff][x - diff];
120+
}
121+
}
122+
}
123+
124+
priority_queue<int, vector<int>, greater<int>> pq;
125+
unordered_set<int> visited;
126+
function<void(int)> add = [&](int sum) {
127+
if (visited.count(sum) == 0) {
128+
visited.insert(sum);
129+
pq.push(sum);
130+
if (pq.size() > 3) {
131+
pq.pop();
132+
}
133+
}
134+
};
135+
for (int y = 0; y < rows; y++) {
136+
for (int x = 0; x < cols; x++) {
137+
for (int l = 1; l <= 50; l++) {
138+
int diff = l - 1;
139+
if (y + 2 * diff >= rows) break;
140+
if (topDp[y][x][l] == INT_MIN ||
141+
downDp[y + 2 * diff][x][l - 1] == INT_MIN)
142+
break;
143+
int cur = topDp[y][x][l] + downDp[y + 2 * diff][x][l - 1];
144+
145+
add(cur);
146+
}
147+
}
148+
}
149+
150+
vector<int> answer;
151+
while (!pq.empty()) {
152+
answer.push_back(pq.top());
153+
pq.pop();
154+
}
155+
reverse(answer.begin(), answer.end());
156+
return answer;
157+
}
158+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Input: grid = [[3,4,5,1,3],[3,3,4,2,3],[20,30,200,40,10],[1,5,5,4,1],[4,3,2,2,5]]
2+
Output: [228,216,211]
3+
4+
===
5+
6+
Input: grid = [[1,2,3],[4,5,6],[7,8,9]]
7+
Output: [20,9,8]
8+
9+
===
10+
11+
Input: grid = [[7,7,7]]
12+
Output: [7]

0 commit comments

Comments
 (0)