O(nlogn) approach
- First maintain a count array cnt[] such that cnt[i] stores frequency of i in your array, as well as a set to keep distinct numbers of your array
- Then go through each number in the set, go through its multiples and add up the cnt[]
Code (Python)
array = [36, 40, 16, 24, 27, 12, 9, 4]
frequency = [0] * 1000001
distinct = set()
for element in array:
frequency[element] += 1
distinct.add(element)
ans = 0
for element in distinct:
current = 0
for multiple in range(element, 1000001, element):
# equivalent to
# for (int multiple = element; multiple <= 1000000; multiple += element)
current += frequency[multiple]
ans = max(ans, current)
print (ans)
Complexity is O(MAXN*logn) worse case because the elements are distinct and the complexity is O(1000000/1+1000000/2+...+1000000/m) and m can be n so O(MAXN*logn)=O(1e6*20) by harmonic series
Note: If you don't want to use a set, maintain another seen
array as well as a distinct
array. Then before you insert simply check if seen[element]
is true.
EDIT: OOPS I MISREAD THE PROBLEM I AM SORRY
Since you only want to count multiples preceding it, you can modify the code such that you store the position of the occurrences, not just the frequency. (i.e. frequency[i] stores [position where i occurred]). You would also need to store the latest position a number appears in the distinct
set, not just te number itself.
Then instead of current += frequency[multiple]
, you should first binary search for the largest index that's <= multiple, then add the number of terms.
The complexity analysis will be left as an exercise :)