[문제 설명]
1와 0로 채워진 표(board)가 있습니다. 표 1칸은 1 x 1 의 정사각형으로 이루어져 있습니다. 표에서 1로 이루어진 가장 큰 정사각형을 찾아 넓이를 return 하는 solution 함수를 완성해 주세요. (단, 정사각형이란 축에 평행한 정사각형을 말합니다.)
예를 들어
1 | 2 | 3 | 4 |
0 | 1 | 1 | 1 |
1 | 1 | 1 | 1 |
1 | 1 | 1 | 1 |
0 | 0 | 1 | 0 |
가 있다면 가장 큰 정사각형은
1 | 2 | 3 | 4 |
0 | 1 | 1 | 1 |
1 | 1 | 1 | 1 |
1 | 1 | 1 | 1 |
0 | 0 | 1 | 0 |
가 되며 넓이는 9가 되므로 9를 반환해 주면 됩니다.
제한사항
- 표(board)는 2차원 배열로 주어집니다.
- 표(board)의 행(row)의 크기 : 1,000 이하의 자연수
- 표(board)의 열(column)의 크기 : 1,000 이하의 자연수
- 표(board)의 값은 1또는 0으로만 이루어져 있습니다.
입출력 예
board | answer |
[[0,1,1,1],[1,1,1,1],[1,1,1,1],[0,0,1,0]] | 9 |
[[0,0,1,1],[1,1,1,1]] | 4 |
[문제 풀이]
이 문제를 처음 접했을때 전체를 검사해야겠다는 생각으로 풀려고 했는데, 반복문이 너무 중첩되어서 이 방법은 안될것 같았다.
따라서 2중 반복문으로 문제를 풀 수 있는 방법을 찾아야했다.
그 방법은 아래와 같다.
왼쪽에서 오른쪽, 위에서 아래로 확인하면서 값을 저장하는 방법이다. 값을 저장하면서 나아가는 로직은 주로 메모이제이션이라고 할 수 있다.
1. 현재 위치의 값이 1이면 아래의 과정을 거친다.
2. 왼쪽[i,j-1], 왼쪽 대각선 위[i-1,j-1], 위[i-1,j] 위치의 값을 확인하고 제일 낮은 값에 1을 더한값을 현재 위치에 저장한다.
=> 2번에서 하는 것은 왼쪽, 왼쪽대각선 위, 위의 값을 확인하여 현재위치에서 만들수 있는 가장 큰 정사각형을 찾아내는 과정이다.
3. 모든 위치를 확인할때까지 1~2번을 반복하고, 가장 큰 값을 answer 변수에 저장한다.
위의 로직대로 코드를 작성하면 문제를 맞출수있다.
내가 짠 로직에서 두번째 줄과 열부터 탐색을 하게 되는데, 이때 조심해야 할 것은 answer의 초기값 설정 부분이다.
무턱대고 0으로 넣어두면 첫번째칸 board[0][0]의 값이 1일때를 캐치하지 못한다.
따라서 answer의 값을 board[0][0]의 값으로 설정해주는것이 맞다.
[코드]
[GitHub]
#include <algorithm>
#include <vector>
using namespace std;
int solution(vector<vector<int>> board)
{
int answer = board[0][0];
int boardYSize = board.size();
int boardXSize = board[0].size();
for(int i = 1 ; i < boardYSize; i++)
{
for(int j = 1; j < boardXSize; j++)
{
if(board[i][j] == 1)
{
board[i][j] = min({board[i-1][j-1], board[i-1][j], board[i][j-1]}) + 1;
answer = max(board[i][j], answer);
}
}
}
return answer*answer;
}
'Problem Solving > 프로그래머스' 카테고리의 다른 글
[프로그래머스] - 가장 가까운 같은 글자(C/C++) (0) | 2022.12.21 |
---|---|
[프로그래머스] - 예상 대진표(C/C++) (0) | 2022.12.20 |
[프로그래머스] - 구명보트(C/C++) (0) | 2022.12.16 |
[프로그래머스] - 점 찍기(C/C++) (0) | 2022.12.15 |
[프로그래머스] - 전력망 둘로 나누기(C/C++) (0) | 2022.12.14 |