https://leetcode.com/problems/search-a-2d-matrix/description/
코드설명
이분탐색(BinarySearch)을 활용합니다.
2D Matrix를 사실상 1D Matrix로 수정해서 풉니다.
이떄 유의점은, matrix 길이가 1일때를 대비하기 위해 아래와 같이 BinarySearch에서 먼저 처리하고 진행합니다.
if(matrix[left/m][left%m] == target) return left; if(matrix[right/m][right%m] == target) return right;
처음에 접근한 비효율적인 방법입니다. (시간복잡도는 O(logM*N) 내에 동작하긴 합니다만, 코드가 길고, 상대적으로 느립니다.)
먼저, row에서 몇번쨰 row에 존재하는지 확인하기 위해 RowBinarySearch를 실행합니다.
이떄, 중요한점은 LowerBound로 처리했으므로, target값보다 더 큰값이 반환될 수 있습니다. 이는, 현재 Matrix[targetRow][0]값과 target값과 같다면 그대로 두고, target 값과 다르다면 -1 처리합니다.
해당 Row값을 가지고서 Matrix[targetRow][Col] 값에 대해서도 똑같이 ColBinarySearch를 실행하여 인덱스 값을 가져오면 됩니다
문제에서 틀릴 수 있는 점은 Edge Case들입니다. 만약 matrix.length == 1 인경우, target이 없어서 범위를 벗어나는 경우 등등 각각 처리를 Edge Case로 처리하느라 main함수의 코드가 많이 복잡합니다. (코드를 잘못짰다는 의미입니다..)
코드
처음에 작성한 코드입니다.
물론, O(log (m * n) )의 시간복잡도를 가지지만, 코드가 상당히 깁니다.
class Solution { public boolean searchMatrix(int[][] matrix, int target) { if(matrix.length == 1){ int targetCol = ColBS(matrix, 0, target, 0, matrix[0].length - 1); if(targetCol < 0 || targetCol >= matrix[0].length) return false; return matrix[0][targetCol] == target; } int targetRow = RowBS(matrix, target, 0, matrix.length - 1); if(targetRow > 0 && targetRow < matrix.length && matrix[targetRow][0] > target){ targetRow = targetRow - 1; } if(targetRow >= matrix.length){ targetRow -= 1; } if(targetRow < 0 || targetRow >= matrix.length) return false; int targetCol = ColBS(matrix, targetRow, target, 0, matrix[0].length - 1); if(targetCol < 0 || targetCol >= matrix[0].length) return false; return matrix[targetRow][targetCol] == target; } int RowBS(int[][] matrix, int target, int start, int end){ int left = start - 1; int right =end + 1; while(left +1 < right){ int mid = (left + right) / 2; if(matrix[mid][0] < target){ left = mid; } else if(matrix[mid][0] >= target){ right = mid; } } return right; } int ColBS(int[][] matrix, int row, int target, int start, int end){ int left = start - 1; int right =end + 1; while(left +1 < right){ int mid = (left + right) / 2; if(matrix[row][mid] < target){ left = mid; } else if(matrix[row][mid] >= target){ right = mid; } } return right; } }
정답코드2입니다.
class Solution { public boolean searchMatrix(int[][] matrix, int target) { int answer = bs(matrix, target, matrix.length, matrix[0].length, 0, matrix.length * matrix[0].length - 1); return target == matrix[answer / matrix[0].length][answer % matrix[0].length]; } int bs(int[][] matrix, int target, int n, int m, int start, int end){ int left = start; int right = end; if(matrix[left/m][left%m] == target) return left; if(matrix[right/m][right%m] == target) return right; while(left + 1 < right){ int mid = (left + right) / 2; int nRow = mid / m; int nCol = mid % m; if(matrix[nRow][nCol] < target){ left = mid; }else if(matrix[nRow][nCol] >= target){ right = mid; } } return right; } }