给定一个nxn矩阵,其中每一行和每一列都按升序排序。给定一个键,如何确定该键是否在矩阵中。
在上一篇文章中讨论了线性时间复杂度。这个问题也可能是分而治之算法的一个很好的例子。以下是分而治之的算法。
1)找到中间元素。
2)如果中间元素与键返回相同。
3)如果中间元素小于键,则
….3a)在中间元素下侧搜索子矩阵
….3b)在中间元素右侧搜索子矩阵
4)如果中间元素大于键,则
….4a)在中间元素的左侧搜索垂直子矩阵
….4b)在右侧搜索子矩阵。
下面实现上述算法。
C++
// C++ program for implementation of
// divide and conquer algorithm
// to find a given key in a row-wise
// and column-wise sorted 2D array
#include
#define ROW 4
#define COL 4
using namespace std;
// A divide and conquer method to
// search a given key in mat[]
// in rows from fromRow to toRow
// and columns from fromCol to
// toCol
void search(int mat[ROW][COL], int fromRow, int toRow,
int fromCol, int toCol, int key)
{
// Find middle and compare with middle
int i = fromRow + (toRow-fromRow )/2;
int j = fromCol + (toCol-fromCol )/2;
if (mat[i][j] == key) // If key is present at middle
cout<<"Found "<< key << " at "<< i <<
" " << j<= fromCol)
search(mat, fromRow, toRow, fromCol, j - 1, key);
}
}
}
// Driver code
int main()
{
int mat[ROW][COL] = { {10, 20, 30, 40},
{15, 25, 35, 45},
{27, 29, 37, 48},
{32, 33, 39, 50}};
int key = 50;
for (int i = 0; i < ROW; i++)
for (int j = 0; j < COL; j++)
search(mat, 0, ROW - 1, 0, COL - 1, mat[i][j]);
return 0;
}
// This code is contributed by Rajput-Ji
Java
// Java program for implementation of divide and conquer algorithm
// to find a given key in a row-wise and column-wise sorted 2D array
class SearchInMatrix
{
public static void main(String[] args)
{
int[][] mat = new int[][] { {10, 20, 30, 40},
{15, 25, 35, 45},
{27, 29, 37, 48},
{32, 33, 39, 50}};
int rowcount = 4,colCount=4,key=50;
for (int i=0; i=fromCol)
search(mat, fromRow, toRow, fromCol, j-1, key);
}
}
}
}
Python3
# Python3 program for implementation of
# divide and conquer algorithm to find
# a given key in a row-wise and column-wise
# sorted 2D array a divide and conquer method
# to search a given key in mat in rows from
# fromRow to toRow and columns from fromCol to
# toCol
def search(mat, fromRow, toRow, fromCol, toCol, key):
# Find middle and compare with middle
i = fromRow + (toRow - fromRow) // 2;
j = fromCol + (toCol - fromCol) // 2;
if (mat[i][j] == key): # If key is present at middle
print("Found " , key , " at " , i , " " , j);
else:
# right-up quarter of matrix is searched in all cases.
# Provided it is different from current call
if (i != toRow or j != fromCol):
search(mat, fromRow, i, j, toCol, key);
# Special case for iteration with 1*2 matrix
# mat[i][j] and mat[i][j+1] are only two elements.
# So just check second element
if (fromRow == toRow and fromCol + 1 == toCol):
if (mat[fromRow][toCol] == key):
print("Found " , key , " at " , fromRow , " " , toCol);
# If middle key is lesser then search lower horizontal
# matrix and right hand side matrix
if (mat[i][j] < key):
# search lower horizontal if such matrix exists
if (i + 1 <= toRow):
search(mat, i + 1, toRow, fromCol, toCol, key);
# If middle key is greater then search left vertical
# matrix and right hand side matrix
else:
# search left vertical if such matrix exists
if (j - 1 >= fromCol):
search(mat, fromRow, toRow, fromCol, j - 1, key);
# Driver code
if __name__ == '__main__':
mat = [[ 10, 20, 30, 40],
[15, 25, 35, 45],
[27, 29, 37, 48],
[32, 33, 39, 50]];
rowcount = 4; colCount = 4; key = 50;
for i in range(rowcount):
for j in range(colCount):
search(mat, 0, rowcount - 1, 0, colCount - 1, mat[i][j]);
# This code is contributed by 29AjayKumar
C#
// C# program for implementation of
// divide and conquer algorithm
// to find a given key in a row-wise
// and column-wise sorted 2D array
using System;
public class SearchInMatrix
{
public static void Main(String[] args)
{
int[,] mat = new int[,] { {10, 20, 30, 40},
{15, 25, 35, 45},
{27, 29, 37, 48},
{32, 33, 39, 50}};
int rowcount = 4, colCount = 4, key = 50;
for (int i = 0; i < rowcount; i++)
for (int j = 0; j < colCount; j++)
search(mat, 0, rowcount - 1, 0, colCount - 1, mat[i, j]);
}
// A divide and conquer method to
// search a given key in mat[]
// in rows from fromRow to toRow
// and columns from fromCol to
// toCol
public static void search(int[,] mat, int fromRow, int toRow,
int fromCol, int toCol, int key)
{
// Find middle and compare with middle
int i = fromRow + (toRow-fromRow )/2;
int j = fromCol + (toCol-fromCol )/2;
if (mat[i, j] == key) // If key is present at middle
Console.WriteLine("Found "+ key + " at "+ i +
" " + j);
else
{
// right-up quarter of matrix is searched in all cases.
// Provided it is different from current call
if (i != toRow || j != fromCol)
search(mat, fromRow, i, j, toCol, key);
// Special case for iteration with 1*2 matrix
// mat[i][j] and mat[i][j+1] are only two elements.
// So just check second element
if (fromRow == toRow && fromCol + 1 == toCol)
if (mat[fromRow,toCol] == key)
Console.WriteLine("Found "+ key + " at "+
fromRow + " " + toCol);
// If middle key is lesser then search lower horizontal
// matrix and right hand side matrix
if (mat[i, j] < key)
{
// search lower horizontal if such matrix exists
if (i + 1 <= toRow)
search(mat, i + 1, toRow, fromCol, toCol, key);
}
// If middle key is greater then search left vertical
// matrix and right hand side matrix
else
{
// search left vertical if such matrix exists
if (j - 1 >= fromCol)
search(mat, fromRow, toRow, fromCol, j - 1, key);
}
}
}
}
// This code has been contributed by 29AjayKumar
输出:
Found 10 at 0 0
Found 20 at 0 1
Found 30 at 0 2
Found 40 at 0 3
Found 15 at 1 0
Found 25 at 1 1
Found 35 at 1 2
Found 45 at 1 3
Found 27 at 2 0
Found 29 at 2 1
Found 37 at 2 2
Found 48 at 2 3
Found 32 at 3 0
Found 33 at 3 1
Found 39 at 3 2
Found 50 at 3 3
时间复杂度:
给定一个* n矩阵,该算法可以看做是对大小为n / 2 xn / 2的3个矩阵的重复。以下是时间复杂度的重复
T(n) = 3T(n/2) + O(1)
复发的解决方案是使用Master方法的O(n 1.58 )。
但是实际的实现需要一个大小为nxn / 2或n / 2 xn的子矩阵,以及另一个大小为n / 2 xn / 2的子矩阵。