1074. Number of Submatrices That Sum to Target

  • m x n 행렬이 μ£Όμ–΄μ‘Œμ„ λ•Œ λΆ€λΆ„ ν–‰λ ¬ μ›μ†Œμ˜ 합이 μ£Όμ–΄μ§„ 숫자 target이 λ˜λŠ” 경우의 수λ₯Ό κ΅¬ν•˜λŠ” 문제.
    • ν–‰λ ¬μ˜ μ΅œλŒ€ ν¬κΈ°λŠ” 100 x 100 이닀.
  • λ‹¨μˆœν•˜κ²Œ λͺ¨λ“  경우의 수λ₯Ό μ‹œλ„ν•΄λ³΄λŠ” 경우 μ‹œκ°„ λ³΅μž‘λ„λŠ” 이 λœλ‹€.
    • λ¨Όμ € λͺ¨λ“  λΆ€λΆ„ ν–‰λ ¬μ˜ 경우의 μˆ˜λŠ” m == n μž„μ„ κ°€μ •ν–ˆμ„ λ•Œ 이닀.
      • ν–‰λ ¬μ˜ ν–‰ μ‹œμž‘ 점, 끝점, μ—΄ μ‹œμž‘μ , 끝점 각각을 λͺ¨λ‘ μ‹œλ„ν•΄λ³΄μ•„μ•Ό ν•œλ‹€.
    • λ”λΆˆμ–΄ 각 λΆ€λΆ„ 행렬에 λŒ€ν•΄μ„œ λͺ¨λ“  μ›μ†Œλ₯Ό λ”ν•˜λŠ” 것은 의 μ‹œκ°„ λ³΅μž‘λ„λ₯Ό κ°€μ§„λ‹€.
    • μ΄λ―€λ‘œ μ˜ˆμƒ μ‹€ν–‰ μ‹œκ°„μ€ κ°€λŸ‰μ΄ λ˜λ―€λ‘œ μ‹œκ°„ μ΄ˆκ³Όκ°€ λœλ‹€ (kλŠ” λ‘œμ§μ„ 1회 μ‹€ν–‰ν•˜λŠ” μ‹œκ°„).
  • 이λ₯Ό 쀄이기 μœ„ν•΄ prefixed sum을 ν™œμš©ν•œλ‹€.
    • ν–‰λ ¬μ˜ 각 행에 λŒ€ν•˜μ—¬ 첫번째 μ—΄ λΆ€ν„° λ§ˆμ§€λ§‰ μ—΄ κΉŒμ§€ λˆ„μ λœ 합을 미리 κ³„μ‚°ν•˜μ—¬ 2d λ°°μ—΄ pSum에 μ €μž₯ν•œλ‹€.
    • 단, κ³„μ‚°μ˜ 편의λ₯Ό μœ„ν•΄μ„œ μ—΄μ˜ 개수 + 1 n + 1 만큼 곡간을 작고 1 번쨰 μ—΄ λΆ€ν„° 값을 μ €μž₯ν•œλ‹€.
    • μ΄λ ‡κ²Œ ν•˜λ©΄ [a, b] μ—΄ λ²”μœ„μ˜ 값을 ꡬ할 λ•Œ pSum[b + 1] - pSum[a]와 같이 ꡬ할 수 μžˆλ‹€.
    • μ—΄ λ²”μœ„μ˜ 값을 λ”ν•˜λŠ” μ‹œκ°„ λ³΅μž‘λ„λ₯Ό μ—μ„œ 둜 κ°μ†Œμ‹œν‚¬ 수 μžˆλ‹€.
  • λͺ¨λ“  λΆ€λΆ„ ν–‰λ ¬μ˜ 경우의 μˆ˜μ— λŒ€ν•΄μ„œ μ›μ†Œμ˜ 합을 κ΅¬ν•˜κ³  κ·Έ 값이 μ£Όμ–΄μ§„ 숫자 target와 λ™μΌν•œ 경우의 수λ₯Ό μ„Όλ‹€.
    • λΆ€λΆ„ ν–‰λ ¬μ˜ ν–‰ λ²”μœ„ [si, ei], μ—΄ λ²”μœ„ [sj, ej]에 λŒ€ν•΄μ„œ μ›μ†Œμ˜ 합을 미리 κ³„μ‚°λœ prefixed sum 배열을 μ΄μš©ν•˜μ—¬ κ΅¬ν•œλ‹€ β†’ .
    • 루프 μˆœμ„œλ₯Ό λ°”κΏ”μ„œ 각 ν–‰ 별 prefixed sum을 λ”ν•˜λŠ” 루프와 λΆ€λΆ„ ν–‰λ ¬μ˜ 경우의 수λ₯Ό νƒμƒ‰ν•˜λŠ” 루프λ₯Ό ν†΅ν•©ν•œλ‹€ β†’ .
    • μ΅œμ’…μ μœΌλ‘œ μ‹œκ°„ λ³΅μž‘λ„λŠ” κ°€ λœλ‹€.
class Solution { public int numSubmatrixSumTarget(int[][] matrix, int target) { int result = 0; int m = matrix.length, n = matrix[0].length; int[][] pSum = new int[m][n + 1]; for (int i = 0; i < m; ++i) { for (int j = 1; j <= n; ++j) { pSum[i][j] = pSum[i][j - 1] + matrix[i][j - 1]; } } for (int sj = 0; sj < n; ++sj) { // μ—΄μ˜ μ‹œμž‘μ  for (int ej = sj; ej < n; ++ej) { // μ—΄μ˜ 끝점 for (int si = 0; si < m; ++si) { // ν–‰μ˜ μ‹œμž‘μ  int sum = 0; for (int ei = si; ei < m; ++ei) { // ν–‰μ˜ 끝점 sum += pSum[ei][ej + 1] - pSum[ei][sj]; if (target == sum) ++result; } } } } return result; } }
  • 루프 μˆœμ„œλ₯Ό λ°”κΎΈμ§€ μ•ŠμœΌλ©΄ μ•„λž˜μ™€ 같이 λ˜λŠ”λ° λ§ˆμ§€λ§‰μ— ν–‰ λ³„λ‘œ prefixed sum을 λ”ν•˜λŠ” λΆ€λΆ„ λ•Œλ¬Έμ— μ‹œκ°„ λ³΅μž‘λ„κ°€ κ°€ λ˜μ„œ μ‹œκ°„ μ΄ˆκ³Όκ°€ λœλ‹€.
    • (2), (5) 번 λ£¨ν”„λŠ” λ˜‘κ°™μ΄ ν–‰ λ²”μœ„λ₯Ό 따라 μ›€μ§μ΄λ―€λ‘œ 이λ₯Ό ν†΅ν•©ν•˜μ—¬ μ›μ†Œμ˜ 합을 κ³„μ‚°ν•˜λŠ” 뢀뢄을 λ‹¨μˆœν™”ν•  수 μžˆλ‹€.
class Solution { public int numSubmatrixSumTarget(int[][] matrix, int target) { ... omitted ... for (int si = 0; si < m; ++si) { // (1) ν–‰μ˜ μ‹œμž‘μ  for (int ei = si; ei < m; ++ei) { // (2) ν–‰μ˜ 끝점: si ~ eiλ₯Ό λ”°λΌμ„œ 순회 for (int sj = 0; sj < n; ++sj) { // (3) μ—΄μ˜ μ‹œμž‘μ  for (int ej = sj; ej < n; ++ej) { // (4) μ—΄μ˜ 끝점 int sum = 0; for (int i = si; i <= ei; ++i) { // (5) si ~ eiκΉŒμ§€ 순회 sum += pSum[i][ej + 1] - pSum[i][sj]; } if (target == sum) { ++result; } } } } } return result; } }