2011-11-11 73 views
6

例如,假設我有一個排序列表我如何獲得列表元素之間的最小差距?

VAL排序=列表(1,5,15,37,39,42,50)

最小間隙爲(39-37)= 2。我將如何獲得這個結果?我一直在尋找foldLeft我感覺它類似於我所需要的,但不完全正確的事情

+1

如果它是一個排序的列表,你可以做一個馬特·芬維克在一次迭代中提出的建議。它將花費O(N)時間。 minGap = minGap Gleeb

回答

3
val sorted = List(1, 5, 15, 37, 39, 42, 50) 
(sorted.tail,sorted).zipped.map(_-_).min 
//res2: Int = 2 

[編輯]

您可以使用摺疊以及:

sorted.tail.foldLeft((sorted.head,Int.MaxValue))((x,y) => (y, math.min(y-x._1,x._2)))._2 
1

這裏是我會做:

  1. 編寫將N個號碼列表功能成的列表(N - 1)間隙

  2. 寫入/使用從列表中選擇最小的數的函數

不要忘記處理空列表殼體F或第1部分! (順便說一句,第2部分可以寫成一個摺疊)。

+0

Can(1)可以在沒有for循環的情況下完成嗎?我試圖使用功能性解決方案@deltanovember – deltanovember

+0

- 當然!有很多純粹的功能方法可以做1。一種方法會使用遞歸! –

12
val sorted = List(1, 5, 15, 37, 39, 42, 50) 

sorted match { 
    case Nil => None 
    case List(a) => None 
    case l => Some(l.sliding(2).map{case Seq(a, b) => math.abs(a - b)}.min) 
} 
// res1: Option[Int] = Some(2) 

sliding返回一個迭代器,以便應該只遍歷一次。

如果您有興趣找到哪兩個元素有最小的缺口,您還可以使用minBy。所以這裏是另一個變化,只是爲了好玩。

sorted.view.zip(sorted.tail).minBy(t => math.abs(t._1 - t._2)) 
// res4: (Int, Int) = (37,39) 
0

勢在必行(可能更快)版本:

if (sorted.isEmpty) { 
    None 
    } else { 
    var sortedTail = sorted.tail 
    if (sortedTail.isEmpty) { 
     None 
    } else { 
     var minDiff = Int.MaxValue 
     var prev = sorted.head 
     do { 
     val curr = sortedTail.head 
     minDiff = minDiff min math.abs(curr - prev) 
     sortedTail = sortedTail.tail 
     prev = curr 
     } while (!sortedTail.isEmpty) 
     Some(minDiff) 
    } 
    } 
1

使用折左:

sorted match {  
     case Nil | List(_) => None 
     case x :: xs => Some(
     (xs.foldLeft((Integer.MAX_VALUE, x)) { 
      case ((min, prev), next) => (math.min(min, next - prev), next) 
     })._1 
    ) 
    } 
相關問題