Я тестировал рекурсивную функцию на производительность.

В строке 33 я создаю массив из 50 000 элементов; каждый элемент в массиве представляет собой Int от 1 до 30.

Тест завершается аварийно, когда массив имеет счетчик примерно> 37500.

Я не совсем уверен, чем вызван этот сбой, но предполагаю, что это связано с переполнением стека? Это на самом деле из-за потока стеков? Учитывая то, что я делаю / этот контекст - нормально ли ожидать переполнения стека?

enter image description here

Код предоставлен ниже для вашего удобства:

 let arr = (1...50000).map { _ in Int.random(in: 1...30) }

    func getBuildingsWithView(_ buildings: [Int]) -> [Int]? {
        if buildings.isEmpty { return nil }
        let count: Int = buildings.count - 1
        var indices: [Int] = []
        let largest: Int = 0
        var buildings = buildings
        hasView(&buildings, &indices, largest, count)
        return indices
    }

    func hasView(_ buildings: inout [Int], _ indices: inout [Int],  _ largest: Int, _ count: Int) {
        if count > 0 {
            var largest = largest
            if (buildings[count] > largest) {
                largest = buildings[count]
            }
            hasView(&buildings, &indices, largest, count-1)
        }
        if (buildings[count] > largest) {
            indices.append(count)
        }
    }

    func test1() {
        print("-----------------TEST START - RECURSION------------------")
        measure {
            print(getBuildingsWithView(arr)!)
        }
        print("-----------------END------------------")
    }
-1
japsoccer 18 Апр 2020 в 14:53

1 ответ

Лучший ответ

Вероятно, это переполнение стека, функция hasView вызывается курсивом с глубиной, примерно равной count, и стек должен хранить count адресов, которые могут превышать размер стека для огромных чисел.

Подробнее в другом сообщении: BAD_ACCESS во время рекурсивных вызовов в Swift

Обратите внимание, что то, что вы реализовали, кажется текущим максимумом в обратном порядке, возвращающим индексы, и это может быть реализовано более эффективно без переполнения, например:

func runningMax(_ arr: [Int]) -> [Int] {
    var max = 0
    var out = [Int]()

    for (i, element) in arr.enumerated().reversed() {
        if element > max {
            max = element
            out.append(i)
        }
    }

    return out.reversed()
}

Я сравнил это с вашим алгоритмом, и результаты кажутся идентичными. Я также тестировал с большими значениями до 100000000, и это нормально.

Возвращаемый массив не обязательно должен быть необязательным, если входной массив пуст, выходной массив - тоже.

1
Louis Lac 18 Апр 2020 в 14:05