[프로그래머스] (LV2) 가장 큰 정사각형 찾기

[프로그래머스] (LV2) 가장 큰 정사각형 찾기

가장 큰 정사각형 찾기

JavaScript, Python

문제 설명

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

입출력 예 설명

입출력 예 #1\
위의 예시와 같습니다.

입출력 예 #2\
| 0 | 0 | 1 | 1 |\
| 1 | 1 | 1 | 1 |\
로 가장 큰 정사각형의 넓이는 4가 되므로 4를 return합니다.


풀이


javascript

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function solution(board) {
var answer = 0;

answer = board.filter((b)=>b.filter((v)=>v===1).length).length > 0 ? 1 : 0

for (let y = 1; y < board.length; y++) {
for (let x = 1; x < board[0].length; x++) {
if (board[y][x] === 1) {
board[y][x] = (Math.min(board[y][x - 1], board[y - 1][x - 1], board[y - 1][x])) + 1;

if (board[y][x] > answer) {
answer = board[y][x];
}
}
}
}
return answer * answer;
}


python

1
2
3
4
5
6
7
8
9
10
11
12
def solution(board):
answer = 0 if sum([sum(b) for b in board]) == 0 else 1

for i in range(1,len(board)):
for j in range(1,len(board[i])):
if board[i][j]:
board[i][j] = min(board[i][j-1],board[i-1][j-1],board[i-1][j]) + 1

if board[i][j] > answer:
answer = board[i][j]

return answer ** 2


설명


배열의 정사각형 부분을 간략히 표현하기 위한 방법을 고민했다.

가장 단순하게 각 점마다 사각형을 확인해보는 함수는 O(N4)까지 효율성이 떨어졌기 때문에, 되도록 O(N2)을 이용하는 방법을 고민했다.

각 열 혹은 행의 합을 이용해서 풀이할 수 있는 방법이 있을까 생각해봤다(스도쿠). 그러나 각 라인 값의 합 만으로는 정사각형을 특정할 수 없었고 결국 배열을 다시 확인하는 작업이 수반되어야 했다.

그러던 중 탐색해 나아갈때마다 값을 누적하는 방식의 풀이를 접하게 되었고, 현재 탐색 점 기준 왼쪽 위로 2x2 사각형의 값을 누적하는 방식의 풀이법을 알게 되었다. 이 때, 3영역의 값 중 최소값을 불러오는데, 이는 사각형을 온전히 이루고 있는지 판단하기 위한 방법이다.


시작

1 1 1
1 1 1
1 1 1


1단계 (1,1)

(1,1) -> [ 상단 : 1 , 좌측 : 1 , 좌측 상단 : 1 ] 이므로 -> 2

1 1 1
1 2 1
1 1 1


2단계 (1,2)

(1,2) -> [ 상단 : 1 ,좌측 : 1 ,좌측상단 : 1 ] 이므로 -> 2

1 1 1
1 2 2
1 1 1


3단계 (2,1)

(2,1) -> [ 상단 : 1 ,좌측 : 1 ,좌측상단 : 1 ] 이므로 -> 2

1 1 1
1 2 2
1 2 1


4단계 (2,2)

(2,2) -> [ 상단 : 2 ,좌측 : 2 ,좌측상단 : 2 ] 이므로 -> 3

1 1 1
1 2 2
1 2 3


이 과정에서 탐색 값 중 0의 값이 포함되어 있다면 현재 값은 오직 1을 갖는다.

따라서 해당 방법으로 (i,j)가 온전한 사각형인지, 만약 그렇다면 얼만큼의 크기를 갖는지 알 수 있다.


출처: 프로그래머스 코딩 테스트 연습, https://programmers.co.kr/learn/challenges


[프로그래머스] (LV2) 가장 큰 정사각형 찾기

https://sklubmk.github.io/2021/06/30/7a56708568fb/

Author

Jinki Kim

Posted on

2021-06-30

Updated on

2021-08-05

Licensed under

댓글