Reputation: 21393
I have a list of numbers, now I want to take a number from the list and check how many elements are there that can divide this number with the remainder as 0.
Here is my code:
public static void countDivibilies(List<Integer> list) {
for (int i = 0; i < list.size(); i++) {
int e = list.get(i);
int count = 0;
for (int j = 0; j < list.size(); j++) {
int k = list.get(j);
if (e % k == 0) {
count++;
}
}
System.out.println(e + " : " + count);
}
}
For sample input:
2, 4, 8, 2
Output is:
2 : 2
4 : 3
8 : 4
2 : 2
But this code runs in O(n2)
time complexity. But my input list size range is up to 105, also each element is between 1 and 105. So how can improve the time complexity of this program?
Upvotes: 1
Views: 1055
Reputation: 11
C++ code-
void countDivisibilities(vector<int> list) {
unordered_map<int, int> freq;
for (int x : list) freq[x]++;
for (int x : list) {
int count = 0;
for (int i = 1; i * i <= x; i++) {
if (x % i == 0) {
count += freq[i];
if (x / i != i) //don't overcount square root
count += freq[x / i];
}
}
cout << x << " : " << count << endl;
}
}
Upvotes: 0
Reputation: 89224
Map
in O(N)
time from the List
.List
in O(sqrt(N))
time. Use the frequency Map
to find how many divisors of the element are in the List
. The total time complexity is O(Nsqrt(N))
.public static void countDivibilies(List<Integer> list) {
Map<Integer, Integer> freq = list.stream()
.collect(Collectors.toMap(x -> x, x -> 1, Integer::sum));
for(int x : list){
int count = 0;
for(int i = 1; i * i <= x; i++){
if(x % i == 0) {
count += freq.getOrDefault(i, 0);
if(x / i != i) //don't overcount square root
count += freq.getOrDefault(x / i, 0);
}
}
System.out.println(x + " : " + count);
}
}
Upvotes: 4