【问题标题】:How can I perform a binary search on a list of objects in Scala如何对 Scala 中的对象列表执行二进制搜索
【发布时间】:2018-09-12 18:59:06
【问题描述】:
case class Employee (id: Int, name : String, age : Int)

// Added four emplyees emp1, emp2 emp3, emp4 to the list like below::

val emp1 = Employee(101, "name1", 101)
val emp2 = Employee(102, "name2", 102)
val emp3 = Employee(103, "name3", 103)
val emp4 = Employee(104, "name4", 104)

list = scala.List(emp1, emp2, emp3, emp4)

我想使用 BINARY SEARCH 在列表中按其姓名搜索员工,并检索该员工对象..

注意:搜索复杂度应为 O(logn),我们不应为此使用任何地图。

类似

val emp = list.binarysearch("name2")
println("the returned employee's age: ", emp.age) //should print 102

任何帮助将不胜感激。!

【问题讨论】:

  • 这个问题看起来像您要求我们为您实现二进制搜索。 How to ask a good question。二进制搜索是一个众所周知的话题,如果你付出一些努力,你应该能够在网上找到足够的资源来理解这一点。
  • 不,这不是我要问的。我不希望有人为我实现任何搜索机制,我自己可以做到这一点。我只需要知道:scala 中是否有任何现有的 api 可以对排序列表执行二进制搜索..并从列表中检索对象如果找到匹配项。
  • 所有二进制搜索实现都涉及对列表/数组上的x'th 索引的随机索引访问,并继续确定要查看的下一个x'th 索引。基本上O(log n) 时间复杂度的二进制搜索要求随机索引访问为constant 时间。但是 Scala 中任何 list: Listlist.get(i)linear 时间,这意味着 Scala 中的 List 无法实现 O(log n) 时间复杂度。
  • 我认为你忽略了我的要求,我已经在说我的列表已经排序了。保持你的想法。我对所有这些细节并不天真。我非常理解好吧..请仔细阅读我的第一条评论,您将了解我的需求..
  • get 的函数ListO(n)。二进制搜索不是在List 上运行的明智算法。如果你改用Array,二分查找可以正常工作,而且代码看起来和其他语言基本一样。

标签: scala big-o binary-search scala-collections


【解决方案1】:

Searching 提供二分搜索,但您需要一个索引序列,而不是线性序列(即List),正如其他人所解释的那样 - 否则您仍然可以使用 search 但您会得到线性 O(n) 行为而不是 O(Log n)。

您说要按名称搜索,因此您需要按名称排序,否则您的结果可能会不一致。你应该研究scala.math.Ordering

因此,如果您可以将列表转换为数组,那么您可以这样做。

case class Employee (id: Int, name : String, age : Int)
val emp1 = Employee(1, "Jane Doe", 45)
val emp2 = Employee(2, "Jon Doe", 54)
val emp3 = Employee(3, "Tera Patrick", 38)
val emp4 = Employee(4, "Jenna Jameson", 36)
// convert to an array
val employees = List(emp1, emp2, emp3, emp4).toArray

// define your ordering
import scala.math.Ordering
implicit object NameOrdering extends Ordering[Employee] {
  def compare(a:Employee, b:Employee) = a.name compare b.name
}

// now sort
import scala.util.Sorting
Sorting.quickSort(employees)(NameOrdering)

然后。

import scala.collection.Searching._

// If the element is found its index is returned
scala> val result = employees.search(emp3)
result: collection.Searching.SearchResult = Found(3)

要检索元素,请对结果使用insertionPoint 方法。

scala> employees(result.insertionPoint)
res6: Employee = Employee(3,Tera Patrick,38)

如果未找到该元素,则返回其插入点在排序序列中的索引。

val emp5 = Employee(5, "Aurora Snow", 34)     // not added

scala> employees.search(emp5)
res2: collection.Searching.SearchResult = InsertionPoint(0)

【讨论】:

    【解决方案2】:

    你永远不能在 O(log n) 中对 scala List() 进行二分搜索,因为我们不能一次丢弃一半列表,我们必须遍历到中间点那。然而它可以用数组来完成。在 Scala 中,您可以创建一个隐式类以在任何 Array[String] 实例上使用 binarySearch() 方法

      implicit class StrArrayOps(strArray: Array[String]) {
        @scala.annotation.tailrec
        private def bs(arr: Array[String], s: Int, e: Int, str: String): Option[Int] = {
          if (e<s) {
            None
          } else {
            val m = (s+e)/2
            val mid = arr(m)
            if (mid == str) {
              Some(m)
            } else {
              if (str.compareTo(mid) > 0) {
                bs(arr, m+1, e, str)
              } else {
                bs(arr, 0, m-1, str)
              }
            }
          }
        }
    
        //returns None if str not found in the strArray
        //returns Some(i) where i is the index of str in the strArray
        def binarySearch(str: String): Option[Int] = bs(strArray, 0, strArray.length-1, str)
      }
    

    你可以像下面这样使用它

    scala> val a = Array("name1", "name2", "name3")
    a: Array[String] = Array(name1, name2, name3)
    
    scala> a.binarySearch("name2")
    res20: Option[Int] = Some(1)
    
    scala> a.binarySearch("name1")
    res21: Option[Int] = Some(0)
    
    scala> a.binarySearch("name3")
    res22: Option[Int] = Some(2)
    
    scala> a.binarySearch("name34")
    res23: Option[Int] = None
    

    【讨论】:

      猜你喜欢
      • 2010-11-01
      • 2022-01-18
      • 2013-12-12
      • 2012-04-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-17
      • 2023-03-04
      相关资源
      最近更新 更多