Given an integer array nums
, return the sum of floor(nums[i] / nums[j])
for all pairs of indices 0 <= i, j < nums.length
in the array. Since the answer may be too large, return it modulo 109 + 7
.
The floor()
function returns the integer part of the division.
Example 1:
Input: nums = [2,5,9] Output: 10 Explanation: floor(2 / 5) = floor(2 / 9) = floor(5 / 9) = 0 floor(2 / 2) = floor(5 / 5) = floor(9 / 9) = 1 floor(5 / 2) = 2 floor(9 / 2) = 4 floor(9 / 5) = 1 We calculate the floor of the division for every pair of indices in the array then sum them up.
Example 2:
Input: nums = [7,7,7,7,7,7,7] Output: 49
Constraints:
1 <= nums.length <= 105
1 <= nums[i] <= 105
This problem asks to calculate the sum of floor(nums[i] / nums[j])
for all pairs of indices (i, j) in the input array nums
. A naive approach with nested loops would result in O(n^2) time complexity, which is inefficient for larger input arrays. The optimal solution uses a clever approach combining counting, prefix sums, and optimized enumeration to achieve significantly better performance.
The solution leverages the following observations:
Counting Element Frequencies: We first count the frequency of each number in nums
using a Counter
(Python) or a similar data structure. This allows us to efficiently access the number of times a specific number appears.
Prefix Sum: A prefix sum array s
is created. s[i]
stores the total count of numbers in nums
that are less than or equal to i
. This enables us to quickly find the number of elements within a given range.
Optimized Enumeration: Instead of brute-forcing all pairs (i, j), we iterate through possible denominators (y
from nums
) and quotients (d
). For each y
and d
, we use the prefix sum array s
to efficiently count the number of numerators (x
in nums
) that satisfy d * y <= x < (d + 1) * y
. The number of such numerators is given by s[min(mx, d * y + y - 1)] - s[d * y - 1]
, where mx
is the maximum value in nums
.
Calculating the Sum: For each valid combination of y
and d
, we add the contribution cnt[y] * d * (number of numerators)
to the total sum, where cnt[y]
is the count of the denominator y
. The modulo operation (% 1000000007
) is applied throughout to prevent integer overflow.
Time Complexity: The outer loop iterates up to mx
(maximum value in nums
), and the inner loop iterates at most mx / y
times for each y
. In the worst case (all numbers are 1), the inner loop dominates, leading to approximately O(mx * log(mx)). Since mx
is bounded by 10^5, this complexity is effectively O(M log M), where M is the maximum value in the array. Creating the prefix sum array and counting frequencies takes O(M) time.
Space Complexity: We use arrays cnt
and s
, both of size mx + 1
, resulting in O(M) space complexity.
from collections import Counter
class Solution:
def sumOfFlooredPairs(self, nums: List[int]) -> int:
mod = 10**9 + 7
cnt = Counter(nums)
mx = max(nums)
s = [0] * (mx + 1)
for i in range(1, mx + 1):
s[i] = s[i - 1] + cnt[i]
ans = 0
for y in range(1, mx + 1):
if cnt[y]:
d = 1
while d * y <= mx:
ans += cnt[y] * d * (s[min(mx, d * y + y - 1)] - s[d * y - 1])
ans %= mod
d += 1
return ans
The code in other languages (Java, C++, Go, TypeScript, Rust) follows a very similar structure, reflecting the same algorithmic approach. The core idea remains the same: utilizing prefix sums and an optimized enumeration strategy to avoid the quadratic time complexity of a naive solution.