Вот простое решение:
func windows<T>(in a: [T], ofSize w: Int) -> [[T]] {
//You could decide here what you want to return if w is invalid
if w > a.count || w <= 0 {
return []
}
var output = [[T]]()
for i in 0..<a.count-w+1 {
output.append(Array(a[i..<i+w]))
}
return output
}
И вот несколько вариантов использования:
windows(in: [1, 3, -5, 2, 6], ofSize: 2) //[[1, 3], [3, -5], [-5, 2], [2, 6]]
windows(in: [1, 3, -5, 2, 6], ofSize: 3) //[[1, 3, -5], [3, -5, 2], [-5, 2, 6]]
Максимум скользящего окна
Расчет скользящего окнаМаксимум при первом создании всех подмассивов расточителен:
let ws = windows(in: [1, 3, -5, 2, 6], ofSize: 3)
let maxs = ws.compactMap { $0.max() } //[3, 3, 6]
Ниже вы можете найти несколько лучших решений:
Подход 1:
Вот два подхода к вычислениюКлассическое раздвижное окно Максимум:
func slidingWindowMax(_ a: [Int], _ w: Int) -> [Int] {
let n = a.count
if n < 2 || w == 1 {
return a
}
var maxLeft = Array(repeating: 0, count: n)
var maxRight = Array(repeating: 0, count: n)
maxLeft[0] = a[0]
maxRight[n - 1] = a[n - 1]
for i in 1..<n {
maxLeft[i] = i % w == 0 ? a[i] : max(maxLeft[i - 1], a[i])
let j = n - i - 1
maxRight[j] = j % w == 0 ? a[j] : max(maxRight[j + 1], a[j])
}
var slidingWindowMax = Array(repeating: 0, count: n - w + 1)
var k = 0
for i in 0 ..< n - w + 1 {
slidingWindowMax[k] = max(maxRight[i], maxLeft[i + w - 1])
k += 1
}
return slidingWindowMax
}
Подход 2:
func slidingWindowMax2(_ array: [Int], _ window: Int) -> [Int]{
let n = array.count
if n < 2 || window == 1 {
return array
}
var result = Array(repeating: 0, count: n - window + 1)
var maxIndex = -1, maximum = Int.max
for start in 0 ..< n - window + 1 {
let end = start + window - 1
if maxIndex < start {
maxIndex = start
maximum = array[start]
for next in start + 1 ... end {
if array[next] > maximum {
maxIndex = next
maximum = array[next]
}
}
} else {
if array[end] > maximum {
maxIndex = end;
maximum = array[end]
}
}
result[start] = maximum
}
return result
}