如何解决计算2d子数组中True的数量
给出2d布尔数组
{{false,false,true,false,true}
{true,false,true,false,false}
{false,true,false,false,false}
{假,假,假,假,假}
{true,true,true,true,true}}
您不能直接访问该数组,它必须通过现成的函数hasTrue 来获取上述2d Array的subArray的起点和终点,如果返回则返回一个布尔值此子数组至少具有1个真
boolean hasTrue(int startX,int startY,int endX,int endY)
例如,如果我们要检查从索引(0,0)到(1,1)的区域,我们将调用hasTrue(0,1,1),并且从索引(1,0开始,它将返回true )的值为true。 我们可以给它一个起点。例如,hasOnes(0,0)只会检查数组中包含值false并返回false的单个索引。
我需要实现一个计算给定子数组中True数量的函数,并且必须使用hasTrue函数。
int countTrues(int startX,int endY)
一种解决方案是从起始索引到末尾进行蛮力计算,并计算具有true的索引的数量。但在最佳情况下,复杂度为n * m。
我正在考虑的另一种解决方案是实现一个递归函数,该函数立即将整个subArray传递给hasOnes(),如果整个subArray返回false,那么我就不需要遍历所有索引,我只需返回0,最好的情况是O(1)。
如果返回True,我将拆分数组并检查每半,并继续这样做并计算True的数量。 我需要实施第二种解决方案的帮助
解决方法
我会以忘记Java的身份编写C ++代码(对不起),但仍然可以为您提供帮助。当然,转换为Java并不困难。它实现了递归地分成两半的想法,实际上它分为四个几乎相等的象限(子矩形)。
>>> [el.get_attribute('innerHTML') for el in wd.find_elements_by_css_selector(".bt__media__content b")]
,
countTrues
函数可以使用递归来实现,基本上,您首先将数组水平分成两半,当剩下的行不多时,将数组垂直分成两半,这很容易理解:
int countTrues(int startX,int startY,int endX,int endY) {
if (!hasTrue(startX,startY,endX,endY)) return 0;
if (startX < endX) {
//split horizontally
return countTrues(startX,(startX + endX) / 2,endY) +
countTrues((startX + endX) / 2 + 1,endY);
} else if (startY < endY) {
//split vertically
return countTrues(startX,(startY + endY) / 2) +
countTrues(startX,(startY + endY) / 2 + 1,endY);
}
//only one value left and is true
return 1;
}
这是一个完整的解决方案:
public class Main {
static boolean array[][] =
{{false,false,true,true},{true,false},{false,true}};
public static void main(String[] args) {
int rowLen = array.length,colLen = array[0].length;
int res = countTrues(0,rowLen - 1,colLen - 1);
System.out.println("number of Trues: " + res);
}
static boolean hasTrue(int startX,int endY) {
while (startX <= endX) {
int indexY = startY;
while (indexY <= endY) {
if (array[startX][indexY]) return true;
indexY++;
}
startX++;
}
return false;
}
static int countTrues(int startX,endY);
}
//only one value left and is true
return 1;
}
}
,
为了以最有效的方式解决此问题,我们必须考虑到hasTrue
返回true时,我们不知道有多少true
存在;但是,当它返回false时,我们知道可以丢弃整个区域,因为它的计数(以及任何子区域的计数)始终为0。因此,我们应该在最大区域上以hasTrue
开始,如果它返回true ,然后分裂并继续;如果返回false,我们可以丢弃整个区域。递归实现:
int countTrues(int startX,int endY) {
int count = 0;
if (endX >= startX && endY >= startY) {
int midX = (endX + startX) / 2;
int midY = (endY + startY) / 2;
// top-left
if (hasTrue(startX,midX,midY)) {
count += countTrues(startX,midY);
}
// top-right
if (hasTrue(midX + 1,midY)) {
count += countTrues(midX + 1,midY);
}
// bottom-left
if (hasTrue(startX,midY + 1,endY)) {
count += countTrues(startX,endY);
}
// bottom-right
if (hasTrue(midX + 1,endY)) {
count += countTrues(midX + 1,endY);
}
}
return count;
}
此实现中的重要元素是仅当hasTrue在特定子区域上返回true时,才对countTrues
进行递归调用。没有这一点,递归实现并不比暴力迭代实现更好。
由于你不能直接访问数组,而只能通过一个hasTrue
方法,你可以使用半除法构建递归countTrues
方法> 方法。您可以使用 IntStream
进行迭代:
static boolean[][] arr = {
{false,true}};
static boolean hasTrue(int startX,int endY) {
// invalid syntax
if (startX > endX || startY > endY)
return false;
return IntStream
// iterate over specified
// range of the rows
.rangeClosed(startX,endX)
// get row by index
// Stream<boolean[]>
.mapToObj(i -> arr[i])
// at least one true in any row
.anyMatch(row -> IntStream
// iterate over specified
// range of the elements
.rangeClosed(startY,endY)
// at least one true in the row
.anyMatch(j -> row[j]));
}
static int countTrues(int startX,int endY) {
// no trues on this iteration
if (!hasTrue(startX,endY))
return 0;
// recursive calls
int lengthX = endX - startX;
int lengthY = endY - startY;
int middleX = lengthX / 2;
int middleY = lengthY / 2;
if (lengthX > 0 || lengthY > 0)
return IntStream
// if 'lengthX > 0' then two iterations X:
// from beginning to middle and from
// middle to end,otherwise one iteration
.rangeClosed(0,lengthX > 0 ? 1 : 0)
.map(i -> i == 0 ? 0 : middleX + 1)
.map(i -> IntStream
// if 'lengthY > 0' then two iterations Y:
// from beginning to middle and from
// middle to end,otherwise one iteration
.rangeClosed(0,lengthY > 0 ? 1 : 0)
.map(j -> j == 0 ? 0 : middleY + 1)
// recursive calls,if it is necessary for
// top-left,top-right,bottom-left,bottom-right
.map(j -> countTrues(startX + i,startY + j,i == 0 ? startX + middleX : endX,j == 0 ? startY + middleY : endY))
.sum())
.sum();
// if it reached this point,this point is true
return 1;
}
public static void main(String[] args) {
System.out.println(hasTrue(1,1,3,3)); // true
System.out.println(countTrues(1,3)); // 2
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。