2011-11-11 3 views
6

Например предположим, у меня есть отсортированный списокКак получить минимальный пробел между элементами списка?

вал отсортировано = Список (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. написать функцию, которая преобразует список п чисел в список (п - 1) зазорами

  2. записи/использовать функцию, которая выбирает наименьшее число из списка

не забудьте обработать пустой список случай п или часть 1! (Кстати, часть 2 может быть написана как складка).

+0

Можно (1) сделать без цикла? Я пытался использовать функциональное решение – deltanovember

+0

@ deltanovember - конечно! Существует множество чисто функциональных способов: 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 
    ) 
    } 
Смежные вопросы