Maximal Rectangle 이란 알고리즘을 비트마스크와 DP를 사용하는 예제로 풀게 되었는데,
상당히 이해하는데 많은 시간이 걸렸기에.. 일단 완벽하게 이해를 하는것 보다 이렇게 작동되는지 알고 코드 흐름을 기억하는 수 밖에 없는 것 같다.
추후에 언젠가 보여질 수 있기 때문에 반복해서 코드를 기억해서 작성하기도 했다.
Given a rows x cols binary matrix filled with 0's and 1's, find the largest rectangle containing only 1's and return its area.
Input: matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]] Output: 6 Explanation: The maximal rectangle is shown in the above picture.
class Solution {
public int maximalRectangle(char[][] matrix) {
int rows = matrix.length;
int cols = matrix[0].length;
// 누적 높이 구하기
int[] heights = new int[cols];
int maxArea = 0;
for(char[] row : matrix) {
for(int i = 0; i < cols; i++) {
heights[i] = (row[i] == '1') ? heights[i] + 1 : 0;
}
// 최대 넓이 갱신하기
maxArea = Math.max(maxArea, getMaxRectangle(heights));
}
return maxArea;
}
public int getMaxRectangle(int[] heights) {
int length = heights.length;
int maxArea = 0;
// stack 써서 최대 사각형 구하기 알고리즘 실행
Stack<Integer> stack = new Stack<>();
for(int i = 0; i <= length; i++) {
// 맨 마지막 고려
int currentHeight = (i == length) ? 0 : heights[i];
while(!stack.isEmpty() && currentHeight < heights[stack.peek()]) {
// 최댓값갱신
int index = stack.pop();
int height = heights[index];
// stack 비원진 것 고려 -> 처음 ~ i 까지 거리
int width = stack.isEmpty() ? i : i - stack.peek() - 1;
maxArea = Math.max(maxArea, height * width);
}
stack.push(i);
}
return maxArea;
}
}
matrix를 순회하면서 heights 배열을 누적해서 반복
연속한 1일 수록 heights 누적하고, 중간에 0이 나오면 초기화 하면서 행을 진행
getMaxRectangle
heights 각 행의 히스토그램이라 생각하고 가장 큰 사각형 넓이를 구하고, 행을 더하면서 각 행에서의 최대 넓이 중 가장 넓은 넓이를 선택
Monotonic Stack 기법 활용
히스토그램(heights) 왼쪽 ~ 끝+1 까지 진행
여기서 +1은 stack에 넣어서 사용하지 않은 히스토그램 막대를 써서 최대의 넓이를 구하는 방식