好吧,我试图在Scala中用二进制搜索找到给定间隔的最小值,但是最小值必须匹配一个给定的函数。 这是我的代码:
def binarySearch: (Int => Boolean) => (Int, Int) => Int = f => (l, h) => {
def bs: ((Int => Boolean) => (Int, Int, Int) => Int) = f => (l, h, minimum) => {
val mid = l + ((h-l) / 2)
mid match{
case mid if(f(mid) == false) => bs(f)(mid+1, h, mid)
case mid if(f(mid) == true && mid > minimum) => bs(f)(l, mid-1, minimum)
case mid if(f(mid) == true && mid < minimum) => bs(f)(mid+1, h, mid)
case mid => mid
}
}
bs(f)(l, h, 0)
}
我认为我的问题是,我没有正确保存最小值。
一个测试用例可能看起来像这样:
val v = Vector(0, 1, 2, 3, 7, 9)
binarySearch(v(_) < 5)(0, v.length) == 4
有什么想法吗?
答案 0 :(得分:2)
这种声明方法的样式非常不寻常,使您的代码难以阅读和理解。因此,我的第一步是以一种更加惯用的,传统的方式重现您的代码。
我采取的步骤如下:
Boolean
-p
。bs
中,其谓词函数参数的重新声明是多余的;它可以重新使用提供给binarySearch
的谓词,因此不需要重新声明它。Boolean
值时,通常让该值保持不变。也就是说,如果boolExpr
是具有值Boolean
或true
的{{1}}表达式,则相对于false
和{{1 }}到if(boolExpr)
。if(boolExpr == true)
。这比您代码中的if(!boolExpr)
更加清楚。您的原始代码将变为:
if(boolExpr == false)
好的,现在我们来调试您的功能。您声称它应计算给定间隔的最小值,并且最小值必须与也给定的函数匹配。或者,换句话说,它应该在满足谓词的范围内找到最小值。
但是,在您的测试用例中,您的断言是该值必须小于5,并且您希望该值4作为答案。
一些问题很明显:
case _
,case mid
,def binarySearch(p: Int => Boolean)(l: Int, h: Int): Int = {
def bs(l: Int, h: Int, minimum: Int): Int = {
val mid = l + ((h - l) / 2)
mid match {
case mid if(!p(mid)) => bs(mid+1, h, mid)
case mid if(p(mid) && mid > minimum) => bs(l, mid-1, minimum)
case mid if(p(mid) && mid < minimum) => bs(mid+1, h, mid)
case _ => mid
}
}
bs(l, h, 0)
}
和l
都是属于h
的值的索引,而mid
无法访问该值,但是它们本身不是价值。这与您要寻找最小值的陈述相矛盾;相反,您似乎正在寻找最小值的 index 。minimum
。Vector
中的binarySearch
小于binarySearch(v(_) >= 5)(0, v.length)
,这表明您没有搜索范围。如果在l
中发生了这种情况,则应将其视为终止条件(已完全搜索范围),并返回找到的最小值索引。 (您现有的代码中似乎没有这样的终止条件,因此它可以在某些情况下无限循环,最终导致h
。)binarySearch
,会发生什么? (提示:您的函数将需要访问范围内的每个元素以确保找到最小值,而这并不是二进制搜索的目的。)bs
,如果找不到值,则返回值StackOverflowError
,否则返回binarySearch(v(_) % 2 == 0)(0, v.length)
。Option[Int]
传递None
,则如果检查具有该索引的元素的值,则会引发Some(minimum)
。您应该改为传递v.length
,或将h
视为超出范围末端的一个位置。更新
为了解决您的实施问题,我对问题进行了略微调整。现在,IndexOutOfBoundsException
函数使用二进制搜索来查找大于指定最小值的最小值。为此,它接受名为v.length - 1
的{{1}}和可以接受的h
值,而不是具有低和高索引的谓词函数。
binarySearch
以下是 Scala REPL 中的一些示例:
IndexedSeq
答案 1 :(得分:0)
我的代码很复杂,需要使用辅助函数。.这可能是正确的解决方案:
def binarySearch: (Int => Boolean) => (Int, Int) => Int = f => (l, h) => {
val mid = l + ((h-l) / 2)
mid match {
case _ if(l >= h) => h
case mid if(f(mid)) => binarySearch(f)(l,mid)
case mid => binarySearch(f)(mid+1, h)
}
}
不幸的是,我们必须使用这种声明方法的方式