<p>Write an efficient algorithm that searches for a value <code>target</code> in an <code>m x n</code> integer matrix <code>matrix</code>. This matrix has the following properties:</p>

<ul>
	<li>Integers in each row are sorted in ascending from left to right.</li>
	<li>Integers in each column are sorted in ascending from top to bottom.</li>
</ul>

<p>&nbsp;</p>
<p><strong class="example">Example 1:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2020/11/24/searchgrid2.jpg" style="width: 300px; height: 300px;" />
<pre>
<strong>Input:</strong> matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5
<strong>Output:</strong> true
</pre>

<p><strong class="example">Example 2:</strong></p>
<img alt="" src="https://assets.leetcode.com/uploads/2020/11/24/searchgrid.jpg" style="width: 300px; height: 300px;" />
<pre>
<strong>Input:</strong> matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20
<strong>Output:</strong> false
</pre>

<p>&nbsp;</p>
<p><strong>Constraints:</strong></p>

<ul>
	<li><code>m == matrix.length</code></li>
	<li><code>n == matrix[i].length</code></li>
	<li><code>1 &lt;= n, m &lt;= 300</code></li>
	<li><code>-10<sup>9</sup> &lt;= matrix[i][j] &lt;= 10<sup>9</sup></code></li>
	<li>All the integers in each row are <strong>sorted</strong> in ascending order.</li>
	<li>All the integers in each column are <strong>sorted</strong> in ascending order.</li>
	<li><code>-10<sup>9</sup> &lt;= target &lt;= 10<sup>9</sup></code></li>
</ul>

class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:

        #Brute Force

        # for i in range(len(matrix)):
        #     for j in range(len(matrix[0])):
        #         if(matrix[i][j]==target):
        #             return True
        # else:
        #     return False

        #Better


        # for sub_matrix in matrix:
        #     d=self.search(sub_matrix,target)
        #     if(d==True):
        #         return True
        # else:
        #     return False

        #Optimal

        i=0
        j=len(matrix[0])-1
        while(i<len(matrix) and j>=0):
            if(target==matrix[i][j]):
                return True
            elif(target<matrix[i][j]):
                d=self.search(matrix[i],target)
                if(d==True):
                    return True
                else:
                    i+=1
                    j-=1
            else:
                d=self.search_col(matrix,i,j,target)
                if(d==True):
                    return True
                else:
                    i+=1
                    j-=1
        else:
            return False
    def search_col(self,matrix,i,j,target):
        low=i
        high=len(matrix)-1
        while(low<=high):
            mid=(low+high)//2
            if(matrix[mid][j]==target):
                return True
            elif(matrix[mid][j]<target):
                low=mid+1
            else:
                high=mid-1
        else:
            return False
    def search(self,nums,target):
        low=0
        high=len(nums)-1
        while(low<=high):
            mid=(low+high)//2
            if(nums[mid]==target):
                return True
            if(nums[mid]<target):
                low=mid+1
            else:
                high=mid-1
        return False
22900