Search code examples
algorithmprime-factoring

O(N*log(log(N))) algorithm for Codility's Peaks?


The task description is here: https://codility.com/demo/take-sample-test/peaks It's also here: Codility Peaks Complexity

First, I tried solving this myself but was only able to come up with what I believed to be a brute force solution. However, it scored 100/100: https://codility.com/demo/results/demoRNWC3P-X4U

Which obviously is completely unsatisfying for me. ;) The outer loop is called for each factor of N (or for each peak, whichever is smaller) and the inner one is called for each peak (just checking if there's a peak in every block). Maybe that's O(N^2), maybe a bit better (since it passes the tests in time limits) but I'm almost sure it's not O(N*log(log(N))).

Then I tried searching for an O(N*log(log(N))) solution but everyone else seems to have a pretty similar solution to mine.

So does anyone have an idea for an O(N*log(log(N))) (or a better one) solution?

Also, if anyone could tell me what complexity my solution has I'd be grateful.


Solution

  • Your code is O(n d(n)) where d(n) is the number of divisors of n. On [1, 100000], d(n) is maximised at 83160 = 2^3 3^3 5 7 11, which has 126 divisors. According to Wikipedia, d(n) is o(n^epsilon) for every epsilon>0, so it grows rather slowly.

    To get an O(n log log n) solution, build a partial sum array telling you how many peaks are left of each point. Then you can tell whether there's a peak in an interval in O(1) time. Checking a divisor d then takes O(n/d) time. Adding up n/d over all divisors d is the same as adding up d over all divisors d, and the result is, according to the same Wikipedia page, O(n log log n).