arraysswiftbignum

How to speed up manipulating an array with a lot of iterations on arrays of integers?


I've been trying to solve the "array manipulation" problem from HackerRank, with many approaches, but no luck.

func arrayManipulation(n: Int, queries: [[Int]]) -> Int {
    var currentArray = Array(repeating: 0, count: n)
    var newArray = [Int]()
    for (index, _) in currentArray.enumerated() {
        var sum = 0
        for query in queries {
            let a = query[0]
            let b = query[1]
            if (index + 1 <= b) && (index + 1 >= a) {
                sum += query[2]
            }
        }
        newArray.append(sum)
    }
    return newArray.max() ?? 0
}

It perfectly works for small number of input data like:

var n = 5
var queries = [[2, 4, 4], [3, 4, 5]]

How does it work?

  1. First you create an array with n zeros, here: [0, 0, 0, 0, 0].
  2. Iterate over all queries and for every query add query[3] for every element in array with index between query[0] and query[1]. After first query there will be [0, 4, 4, 4, 0] (added 4 to 2nd, 3rd and 4th element), and after the second one [0, 4, 9, 9, 0] (added 5 to 3rd and 4th element). It is not an index, count from zero.
  3. Get maximum from final array. Here 9.

Above example works of course for small data. But when the data for example is like:

var n = 4000
var queries = // array with 30_000 elements where last element k > 800_000

Is there any way to improve performance?


Solution

  • the main problem is that you're iterating over all queries for each element in array, essentially doing O(N^2) operations

    better approach is to calculate prefix sum, ie just store when some query starts/ends and then calculate maximal sum

    func arrayManipulation(n: Int, queries: [[Int]]) -> Int {
        var arr = Array(repeating: 0, count: n+1)
        for query in queries {
            arr[query[0] - 1] += query[2]
            arr[query[1]] -= query[2]
        }
    
        var s = 0
        var m = 0
        for i in 0..<n {
            s += arr[i]
            m = max(m, s)
        }
        return m
    }