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;
    }
}

+ Recent posts