2015-01-05 3 views
2

정수가 들어있는 MxN 크기의 매트릭스가 있습니다. 우리는 같은 정수를 가진 가장 큰 크기의 부분 행렬을 찾아야합니다. 예를 들면 다음과 같습니다.동일한 정수를 갖는 서브 매트릭스의 최대 크기

1 2 2 4 5 
1 2 2 8 7 
3 2 2 6 1 

여기서 가장 큰 부분 행렬은 2를 모두 포함하는 3x2 크기입니다. 내 생각은 arr [i] [j + 1], arr [i + 1] arr [j + 1] 및 arr [i + 1] [j]가 각 요소 arr [i] [j] 같거나 틀리다. 그것들이 같으면 우리는 어떻게해서 행렬의 최대 크기를 업데이트 할 수 있습니다. 그러나 나는 정확한 해결책에 도달 할 수 없었다.

어떻게 든 동적 프로그래밍을 사용할 수 있는지 궁금합니다. 이것은 인터뷰 질문이었습니다.

+0

이 읽기 ​​: 여기

일부 코드가 (이 완전히 구현되지 않으며이 버그를 포함 할 수 있습니다)입니다 http://www.geeksforgeeks.org/maximum-size-sub-matrix-with -all-1s-in-a-binary-matrix/간단한 변화로 DP 알고리듬을 가짐 :) – Lrrr

+1

@AliAmiri 서브 매트릭스가 여기에 정사각형 일 필요가 없기 때문에이 것이 더 어렵다. – kraskevich

+0

@ILoveCoding이 사람이 더 힘들다는 것을 알고 있지만 같은 생각이 도움이 될 것이라고 생각합니다. (현재 직장에 있는데, 집에 도착했을 때 해결책에 대해 생각합니다) – Lrrr

답변

2
  1. 부분 행렬의 맨 아래 행이 고정되어 있다고 가정합시다. 그런 다음 각 열은 쌍 (값, 높이)으로 표현 될 수 있습니다. 여기서 value는이 행과 열의 요소 값이고 height는이 열의 연속 요소 수와 동일합니다. 상기 값은 예를 들어, 행렬은

    3 1 2 3 
    1 2 2 1 
    3 2 2 1 
    2 2 2 2 
    

    경우 우리가보고있는 바닥 행 (제로 인덱스에서) 2 (3, 1), (2, 2), (2, 3), (1, 2)로 나타낼 수있다.

  2. 같은 값을 가진 인접한 요소를 그룹화하여 그룹으로 나누어 봅시다 (이전 예제에서는 {(3,1)}, {(2,2), (2, 3)} 및 { 이제 우리는 표준 문제를 해결할 수 있습니다 : 값 배열 h[i]이 주어지면 각 그룹 내에서 ij에 대해 min(h[i], h[i + 1], ..., h[j]) * (j - i + 1)의 가장 큰 값을 찾습니다 (스택을 사용하는 선형 솔루션이 있습니다. 자세한 내용은 다음을 참조하십시오). 선형 시간에 하나의 행을 처리 할 수 ​​있습니다.

  3. 마지막으로 필요한 것은 각 행의 (값, 높이) 배열을 효율적으로 계산하는 것입니다. 첫 번째 행에 대해서는 사소한 것입니다 따라서 모든 행과 행을 하나씩 반복 할 수 있습니다. (한 요소가 열의 맨 아래에 추가되면 (값, 높이) 쌍이 두 가지 방법으로 변경됩니다. 즉, (new_value, 1) 또는 (value, height + 1)이됩니다.

이러한 관찰 결과, O(M) 시간에서 하나의 행을 처리 할 수있다. 총 시간 복잡도는 O(N * M)입니다.

int solve() { 
    int res = 0; 
    Pair[] valueForColumn = new Pair[rowsCount]; 
    for (int col = 0; col < columnsCount; col++) 
     valueForColunm[col] = new Pair(matrix[0][col], 1); 
    res = Math.max(res, solveForRow(valueForColumn); 
    for (int row = 1; row < rowsCount; row++) { 
     for (int col = 0; col < columnsCount; col++) 
      if (matrix[row][col] == matrix[row - 1][col]) { 
       valueForColumn[col].second++; 
      } else { 
       valueForColumn[col].first = matrix[row][col]; 
       valueForColumn[col].second = 1; 
      } 
     } 
     res = Math.max(res, solveForRow(valueForColumn)); 
    } 
    return res; 
} 

int solveForRow(Pair[] valueForColumn) { 
    List<Integer> group = new ArrayList<>(); 
    int res = 0; 
    for (int i = 0; i < valueForColumn.length; i++) { 
     group.add(valueForColumn[i].second); 
     if (i == valueForColumn.length - 1 
       || valueForColumn[i].first != valueForColumn[i + 1].first) { 
      res = Math.max(res, solveForGroup(group)); 
      group.clear(); 
     } 
    } 
    return res; 
} 

int solveForGroup(List<Integer> heights) { 
    // a stack-based algorithm 
    // with linear time complexity mentioned in 2. goes here 
} 
+0

나는 당신이 가정 한 부분을 이해하지 못했습니다. 하단 행 고정. 당신은 그 것을 설명해 주시겠습니까 – h4ck3d

+0

그리고 우리는 각 행마다 이것을해야합니까? 먼저 하위 행렬부터 시작합니다. 하위 행렬이이 행의 일부가 아닌 경우 상단 행으로 이동하여 동일한 알고리즘을 따라야합니다. 의사 코드 등을 제공 할 수 있습니까? – h4ck3d

관련 문제