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?
array
with n
zeros, here: [0, 0, 0, 0, 0]
.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.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?
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
}