[英]searching in 2d array as O(n) with unsorted rows
我需要编写一个方法,该方法采用2d数组'int [] [] m'和值'val'并检查val是否在数组中的复杂度为O(n),而n定义为行数和m必须平方
可用作my方法参数的数组必须为此方法返回true:
(如果它返回true,那么数组是按要求的)
public static boolean test(int[][] m) {
int n = m.length;
for (int r = 0; r < (n - 1); r++)
for (int c = 0; c < n; c++)
for (int i = 0; i < n; i++)
if (m[r][c] > m[r + 1][i]) return false;
return true;
}
此数组返回TRUE:
int [][] arr3 = new int [][]{
{ 0, 2, 1, 2, 0, 5, 5, 5, },
{ 21, 21, 7, 7, 7, 21, 21, 21 ,},
{ 21, 21, 21, 21, 21, 21, 21 , 21, },
{ 21, 21, 23 , 42, 41, 23, 21, 21, },
{ 60 ,56, 57, 58, 53, 52, 47, 51 ,},
{ 61, 65, 70 , 72, 73, 78, 82, 98 ,},
{ 112, 121, 112, 134, 123, 100, 98, 111,},
{ 136, 136, 136, 134, 147, 150, 154, 134,},
};
如果val
在数组中,我的方法应返回true,如下所示:
public boolean findValTest(int [][] m, int val){...}
iff可能。 矩阵m
是大小为n×n的方阵。 核心理念的灵感来自oleg.cherednik的答案 。 一旦我们找到一个row
在m
,使得m[row][0] >= val
,我们知道val
必须是行中的row
或row - 1
(因为在同一比较row - 1
为false
)。 因此,我们必须找到我们的候选行( O(n) ),然后只分析那两行(也是O(n) )。 如果m
不是方形,而是矩形,则算法具有O(n + k)的复杂度,其中n是行数, k是以m
为单位的列数。 这导致以下算法。
public class Test {
public static boolean contains(final int[][]m, final int value) {
int candidateRow = m.length;
for (int row = 1; row < m.length; ++row) {
if (m[row][0] == value) {
return true;
}
if (m[row][0] > value) {
candidateRow = row;
break;
}
}
for (int val : m[candidateRow - 1]) {
if (val == value) {
return true;
}
}
if (candidateRow < m.length) {
for (int val : m[candidateRow]) {
if (val == value) {
return true;
}
}
}
return false;
}
public static void main(String[] args) {
int [][] testArray = new int [][]{
{ 0, 2, 1, 2, 0, 5, 5, 5 },
{ 21, 21, 7, 7, 7, 21, 21, 21 },
{ 21, 21, 21, 21, 21, 21, 21, 21 },
{ 21, 21, 23, 42, 41, 23, 21, 21 },
{ 60, 56, 57, 58, 53, 52, 47, 51 },
{ 61, 65, 70, 72, 73, 78, 82, 98 },
{ 112, 121, 112, 134, 123, 100, 98, 111 },
{ 136, 136, 136, 134, 147, 150, 154, 134 }
};
for (int[] row : testArray) {
for (int val : row) {
System.out.print(contains(testArray, val) + " ");
}
System.out.println();
}
System.out.println();
System.out.println();
final int[] notInMatrix = { -1, 3, 4, 6, 8, 22, 30, 59, 71, 113, 135 };
for (int val : notInMatrix) {
System.out.print(contains(testArray, val) + " ");
}
System.out.println();
}
}
我们可以通过二进制搜索算法确定候选行来改善实际运行时间,以便在O(log(n))而不是O(n)中找到候选行。 对于方形矩阵,渐近运行时仍然是O(n) ,对于非方形nxk矩阵,渐近运行时仍然是O( log(n)+ k) 。 这个想法取自Saeed Bolhasani的回答 。
private static int findCandidateRow(final int[][] m, final int value) {
int lower = 0;
int upper = m.length;
int middle = (upper + 1) / 2;
while (middle != m.length
&& middle != 1
&& (m[middle][0] < value || m[middle - 1][0] > value)) {
if (m[middle][0] < value) {
lower = middle;
} else {
upper = middle;
}
middle = lower + (upper - lower + 1) / 2;
}
return middle;
}
水木清华。 像那样。 如果第i
行的每个数字等于或小于第i+1
行的每个数字 ,则只能检查每行中的第一个元素以定义行,其中所需的值可以是。 只有完全扫描才能找到未排序行中的元素。
该算法必须仅扫描2个完整行 ,即O(n) ,其中n - 行数 。
public static boolean findValTest(int[][] m, int val) {
for (int row = 0; row < m.length; row++) {
if (m[row][0] <= val && row != m.length - 1)
continue;
int r = row;
while (r >= row - 1 && r >= 0) {
for (int col = 0; col < m[r].length; col++)
if (m[r][col] == val)
return true;
r--;
}
return false;
}
return false;
}
测试用例:
System.out.println(findValTest(arr3, -1)); // false
System.out.println(findValTest(arr3, 5)); // true
System.out.println(findValTest(arr3, 7)); // true
System.out.println(findValTest(arr3, 55)); // false
System.out.println(findValTest(arr3, 47)); // true
System.out.println(findValTest(arr3, 147)); // true
System.out.println(findValTest(arr3, 200)); // false
System.out.println(findValTest(new int[][] { { 3, 4, 5 } }, 4)); // true
你的解决方案在这里。 我做了一个函数,对第一列进行二进制搜索。 如果val在第一列中找到该函数,则返回true,否则最后一段'l'和'r'对我们有利。 'r'和'l'总是等于只有一个距离(r = l或abs(rl)= 1)。 'r'和'l'的下限是val可能存在于其中的预期行。 所以我们应该搜索这一行。
二进制搜索的O(n)是Log(n),行搜索是n。 所以最后的O(n)将是n.code在这里:
static boolean binarySearch(int arr[][], int l, int r, int x)
{
if (r>=l)
{
int mid = l + (r - l)/2;
// If the element is present at the
// middle itself
if (arr[mid][0] == x)
return true;
// If element is smaller than mid, then
// it can only be present in left subarray
if (arr[mid][0] > x)
return binarySearch(arr, l, mid-1, x);
// Else the element can only be present
// in right subarray
return binarySearch(arr, mid+1, r, x);
}
// We reach here when element is not present
// in array
int row = Math.min(l,r);
for(int i=0; i<arr[0].length ;i++)
if(arr[row][i]==x)
return true;
return false;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.