我找不到有关Scala的任何文档,但是对于从未使用或很少使用递归的其他编程语言,却找不到很多文档。
应该允许该序列为空并且包含双精度数。
val nonEmpthySeq = Seq(1,2,3,4,4,4,5,6,7,7,67,8,9,9,10)
val oneElementSeq = Seq(4)
val empthySeq = Seq()
我无法为此回答,因为我的问题可能是重复的。
使用模式匹配
def secondSmallest(xs: Seq[Int]): Option[Int] = xs match {
case Nil => None
case `xs` => Some(xs.distinct.sorted.apply(1))
}
超级干净的单缸纸
def secondSmallest(xs: Seq[Int]): Option[Int] =
Try(xs.distinct.sorted.apply(1)).toOption
两个都返回
secondSmallest(nonEmpthySeq)
secondSmallest(oneElementSeq)
secondSmallest(empthySeq)
res0: Option[Int] = Some(2) res1: Option[Int] = None res2: Option[Int] = None
res1
解释:
x::Nil
,对于Seq(4)
中的secondSmallest(oneElementSeq)
必须为None
,因为逻辑上列表中没有第二高元素,因此它必须为None
。
如果只需要一个元素,则必须使用case x :: Nil => Some(x)
处理它。
def secondSmallest(xs: Seq[Int]): Option[Int] = xs match {
case Nil => None
case x :: Nil => Some(x)
case `xs` => Some(xs.distinct.sorted.apply(1))
}
答案 0 :(得分:3)
又快又脏
list.distinct.sorted.lift(1)
lift
部分处理的情况是位置1
上没有条目。
适当的线性解
此方法在O(n)
中有效,只扫描一次列表:
def secondLargest[A: Ordering](as: Seq[A]): Option[A] = {
val bottom = Option.empty[A]
val ord = implicitly[Ordering[Option[A]]]
import ord._
as.foldLeft((bottom, bottom)) {
case ((largest, second), x) =>
val wrapped = Some(x)
if (wrapped > largest) (wrapped, largest)
else if (wrapped > second) (largest, wrapped)
else (largest, second)
}._2
}
在扫描序列时,它会保留两个Option[A]
,其中两个元素最大。对Option[A]
进行比较的原因在于,Ordering
提供了一个隐式形式,该隐式形式将None
作为底部元素与类型A
上的任何排序(这是ord
)。
示例:
println(secondLargest(Seq("foo", "bar", "baz")))
println(secondLargest(Seq(4, 7, 2, 5, 9, 6, 4)))
打印:
// Some(baz)
// Some(7)
请注意,所有基于热切排序的解决方案都至少为O(n*log(n))
,这是不好的,因为存在一种快速选择算法,可以在预期的线性时间内找到k
最大的元素。
修改
哦,好吧...如果要第二个最小,请颠倒顺序:
def secondSmallest[A: Ordering](as: Seq[A]): Option[A] =
secondLargest(as)(implicitly[Ordering[A]].reverse)
println(secondSmallest(Seq("aa", "ca", "ab", "bc", "cc"))) // Some(ab)
println(secondSmallest(Seq(4, 7, 2, 5, 9, 6, 4))) // Some(4)
答案 1 :(得分:2)
警告:在遵循此答案之前,请注意安德烈的评论。
这是我在评论中从蒂姆偷来的一个解决方案:
def secondHighest(xs:Seq[Int]): Option[Int] = {
xs.distinct.sorted.init.lastOption
}
和
def secondLowest(xs:Seq[Int]): Option[Int] = {
xs.distinct.sorted.drop(1).headOption
}
我自己的误导尝试是
Try(xs.distinct.sorted.apply(1)).toOption
答案 2 :(得分:1)
此类使用堆来实现优先级队列。
从堆数据结构上的Wikipedia page:
Heap数据结构可用于有效地找到数组中第k个最小(或最大)的元素。
在这种情况下,也许我们可以在不牺牲太多效率的情况下推广问题。
def fromTop[A:Ordering](xs :Seq[A], offset :Int) :Option[A] = {
val pq = collection.mutable.PriorityQueue(xs:_*)
for (_ <- 1 until offset) {
val init = pq.headOption
while (pq.nonEmpty && pq.head == init.get)
pq.dequeue()
}
pq.headOption
}
def fromBottom[A:Ordering](xs :Seq[A], offset :Int) :Option[A] =
fromTop(xs, offset)(implicitly[Ordering[A]].reverse)
测试:
fromTop(Vector.empty[Int], 2) //res0: Option[Int] = None
fromTop(Vector(9, 88), 0) //res1: Option[Int] = Some(88)
fromTop(Vector('a','c','t','u','p'), 3) //res2: Option[Char] = Some(p)
fromBottom(List(true,false,true), 2) //res3: Option[Boolean] = Some(true)
fromBottom(List(1,2,3), 4) //res4: Option[Int] = None
fromBottom(List(1,1,1,2,2,2,3,3,3), 2) //res5: Option[Int] = Some(2)