leetcode - 240.Search a 2D Matrix II
2017-03-11 20:14
357 查看
算法系列 — leetcode
题目描述:
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
Integers in each row are sorted in ascending from left to right.
Integers in each column are sorted in ascending from top to bottom.
If there is an element equal to the value, return True; otherwise return False.
如果target = mark,找到返回True
如果target > mark,则向下搜索
如果target < mark,则向左搜索
直至出界,则说明没有这个元素,返回False
矩阵每行都是从左至右升序,每列都是从上到下升序,如果target在矩阵中某个位置
初始mark在整个矩阵的右上角,所以target在其左下方
每次搜索只移动一步,移动的规则也总是能够保证移动之后target仍然是在mark左下方
那么在经过有限步移动之后target必然和mark重合
mark向下最多移动m步,向左最多移动n步,因而时间复杂度为O(m+n)
无论怎样看,这个解法都非常精简优雅,不过,我最初的目的是要练习分治算法,似乎这个解法里面并没有分治的思想
不难分析算法时间复杂度为O(N*logM)或者O(M*logN)
这个算法看起来就既没有技术含量也没有上面的那个算法优雅了,不过至少不是O(M*N)
最简单的就是将矩阵二等分或者四等分,但是矩阵各个部分都是不同的,因此很难通过减少重复动作来降低复杂度
只能通过剪枝来减小递归系数,而等分矩阵很难进行剪枝
从剪枝这个角度入手,自然是想将矩阵中不可能存在target的部分给抛弃掉
假设matrix[i][j] < target,那么它左上方的子矩阵便可全部抛弃
如果还有matrix[i+1][j+1] > target, 那么此元素右下方的子矩阵也可全部抛弃
因而只需要对matrix[i][j]左下方和右上方的两个子矩阵再进行查找,然后将两个结果归并起来即可
注意到对角线(i=j,在矩阵中不是很严格)上的元素也是升序的,因而可以通过二分查找来确定这个划分矩阵的关键元素
此处的复杂度分析涉及到两个变量,且关键元素位置不是确定的,因而比较困难,我再研究研究
不过估算应该是介于O(M*logN)和O(M+N)之间的; 边界条件不再累述,代码之中会有所反映
这个算法虽然没有第一个算法那么简洁并且高效,比第二个算法看上去也复杂了一点,
在这个问题上也没有收获到很大的成果,但是在这个过程中对分治的思想训练很有帮助
作为刚上路的菜鸟,慢慢学吧,总会好的
题目描述:
Write an efficient algorithm that searches for a value in an m x n matrix. This matrix has the following properties:
Integers in each row are sorted in ascending from left to right.
Integers in each column are sorted in ascending from top to bottom.
If there is an element equal to the value, return True; otherwise return False.
最最理想的解法,复杂度为O(m+n),不过我并没有想到
直接从矩阵的右上角开始搜索, 用mark表示搜索位的所有信息如果target = mark,找到返回True
如果target > mark,则向下搜索
如果target < mark,则向左搜索
直至出界,则说明没有这个元素,返回False
矩阵每行都是从左至右升序,每列都是从上到下升序,如果target在矩阵中某个位置
初始mark在整个矩阵的右上角,所以target在其左下方
每次搜索只移动一步,移动的规则也总是能够保证移动之后target仍然是在mark左下方
那么在经过有限步移动之后target必然和mark重合
mark向下最多移动m步,向左最多移动n步,因而时间复杂度为O(m+n)
def searchMatrix(matrix, target): i = 0 j = len(matrix[0]) while i < len(matrix) and j >= 0: if matrix[i][j] == target: return True if matrix[i][j] < target: i++ else : j-- return False
无论怎样看,这个解法都非常精简优雅,不过,我最初的目的是要练习分治算法,似乎这个解法里面并没有分治的思想
暴力枚举配合二分法
由于每行和每列都是有序的,很容易就能想到对每行(或每列)进行二分搜索不难分析算法时间复杂度为O(N*logM)或者O(M*logN)
def searchMatrix(matrix, target): cols = len(matrix[0]) for x in range(0, len(matrix)): if matrix[x][0] <= target && matrix[x][cols-1] >= target && binarySearch(matrix[x], target): return True return False def binarySearch(li, target): start = 0 end = len(li) - 1 while(end > start): mid = int((start + end) / 2) if target == li[mid]: return True elif target > li[mid]: start = mid + 1 else : end = mid - 1 return li[end] == target
这个算法看起来就既没有技术含量也没有上面的那个算法优雅了,不过至少不是O(M*N)
分治思想配合二分法
由于给定的矩阵比较特殊,每行每列均是升序的,因而可以缩小矩阵规模以分治最简单的就是将矩阵二等分或者四等分,但是矩阵各个部分都是不同的,因此很难通过减少重复动作来降低复杂度
只能通过剪枝来减小递归系数,而等分矩阵很难进行剪枝
从剪枝这个角度入手,自然是想将矩阵中不可能存在target的部分给抛弃掉
假设matrix[i][j] < target,那么它左上方的子矩阵便可全部抛弃
如果还有matrix[i+1][j+1] > target, 那么此元素右下方的子矩阵也可全部抛弃
因而只需要对matrix[i][j]左下方和右上方的两个子矩阵再进行查找,然后将两个结果归并起来即可
注意到对角线(i=j,在矩阵中不是很严格)上的元素也是升序的,因而可以通过二分查找来确定这个划分矩阵的关键元素
此处的复杂度分析涉及到两个变量,且关键元素位置不是确定的,因而比较困难,我再研究研究
不过估算应该是介于O(M*logN)和O(M+N)之间的; 边界条件不再累述,代码之中会有所反映
def _searchMatrix(matrix, target): return searchMatrix(matrix, target, 0, 0, len(matrix)-1, len(matrix[0])-1) def searchMatrix(matrix, target, si, sj, ei, ej): if si > ei or sj > ej or target < matrix[si][sj]: return False if si == ei: for j in range(sj, ej+1): if target == matrix[si][j]: return True return False elif sj == ej: for i in range(si, ei+1): if target == matrix[i][sj]: return True return False start = 0 end = min((ei - si), (ej - sj)) while end > start + 1: mid = int((start + end) / 2) if target > matrix[si + mid][sj + mid]: start = mid elif target < matrix[si + mid][sj + mid]: end = mid else : return True if target > matrix[si+start+1][sj+start+1]: start += 1 elif target == matrix[si+start+1][sj+start+1] \ or target == matrix[si+start][sj+start]: return True return searchMatrix(matrix, target, si+start+1, sj, ei, sj+start) or searchMatrix(matrix, target, si, sj+start+1, si+start, ej)
这个算法虽然没有第一个算法那么简洁并且高效,比第二个算法看上去也复杂了一点,
在这个问题上也没有收获到很大的成果,但是在这个过程中对分治的思想训练很有帮助
作为刚上路的菜鸟,慢慢学吧,总会好的
相关文章推荐
- Leetcode240. Search a 2D Matrix II
- leetcode 240. Search a 2D Matrix II
- [leetcode]240. Search a 2D Matrix II
- Leetcode 240. Search a 2D Matrix II[medium]
- LeetCode 240. Search a 2D Matrix II
- Leetcode 240. Search a 2D Matrix II (Medium) (cpp)
- LeetCode 240. Search a 2D Matrix II
- Divide and Conquer -- Leetcode problem240. Search a 2D Matrix II
- Leetcode 240. Search a 2D Matrix II
- LeetCode 240. Search a 2D Matrix II
- leetcode 240. Search a 2D Matrix II
- [leetcode]240. Search a 2D Matrix II
- Leetcode 240. Search a 2D Matrix II
- LeetCode *** 240. Search a 2D Matrix II
- 第十八周:[Leetcode]240. Search a 2D Matrix II
- LeetCode--240. Search a 2D Matrix II
- LeetCode 240. Search a 2D Matrix II
- 【LeetCode】 240. Search a 2D Matrix II
- LeetCode 240. Search a 2D Matrix II
- leetcode240. Search a 2D Matrix II