How do I search for a number in a 2d array sorted left to right and top to bottom?

后端 未结 20 942
暖寄归人
暖寄归人 2020-11-22 13:03

I was recently given this interview question and I\'m curious what a good solution to it would be.

Say I\'m given a 2d array where all the numbers i

20条回答
  •  谎友^
    谎友^ (楼主)
    2020-11-22 13:08

    I've been asking this question in interviews for the better part of a decade and I think there's only been one person who has been able to come up with an optimal algorithm.

    My solution has always been:

    1. Binary search the middle diagonal, which is the diagonal running down and right, containing the item at (rows.count/2, columns.count/2).

    2. If the target number is found, return true.

    3. Otherwise, two numbers (u and v) will have been found such that u is smaller than the target, v is larger than the target, and v is one right and one down from u.

    4. Recursively search the sub-matrix to the right of u and top of v and the one to the bottom of u and left of v.

    I believe this is a strict improvement over the algorithm given by Nate here, since searching the diagonal often allows a reduction of over half the search space (if the matrix is close to square), whereas searching a row or column always results in an elimination of exactly half.

    Here's the code in (probably not terribly Swifty) Swift:

    import Cocoa
    
    class Solution {
        func searchMatrix(_ matrix: [[Int]], _ target: Int) -> Bool {
            if (matrix.isEmpty || matrix[0].isEmpty) {
                return false
            }
    
            return _searchMatrix(matrix, 0.., _ columns: Range, _ target: Int) -> Bool {
            if (rows.count == 0 || columns.count == 0) {
                return false
            }
            if (rows.count == 1) {
                return _binarySearch(matrix, rows.lowerBound, columns, target, true)
            }
            if (columns.count == 1) {
                return _binarySearch(matrix, columns.lowerBound, rows, target, false)
            }
    
            var lowerInflection = (-1, -1)
            var upperInflection = (Int.max, Int.max)
            var currentRows = rows
            var currentColumns = columns
            while (currentRows.count > 0 && currentColumns.count > 0 && upperInflection.0 > lowerInflection.0+1) {
                let rowMidpoint = (currentRows.upperBound + currentRows.lowerBound) / 2
                let columnMidpoint = (currentColumns.upperBound + currentColumns.lowerBound) / 2
                let value = matrix[rowMidpoint][columnMidpoint]
                if (value == target) {
                    return true
                }
    
                if (value > target) {
                    upperInflection = (rowMidpoint, columnMidpoint)
                    currentRows = currentRows.lowerBound.., _ target: Int, _ searchRow : Bool) -> Bool {
            if (range.isEmpty) {
                return false
            }
    
            let midpoint = (range.upperBound + range.lowerBound) / 2
            let value = (searchRow ? matrix[rowOrColumn][midpoint] : matrix[midpoint][rowOrColumn])
            if (value == target) {
                return true
            }
    
            if (value > target) {
                return _binarySearch(matrix, rowOrColumn, range.lowerBound..

提交回复
热议问题