📌  相关文章
📜  给定数组中所有对的楼层划分总和

📅  最后修改于: 2021-04-27 20:37:50             🧑  作者: Mango

给定大小为N的数组arr [] ,任务是找到所有索引对(i,j)的底值(arr [i] / arr [j])的总和。

例子:

天真的方法:解决此问题的最简单方法是生成数组的所有可能对,并为每个对将结果的下限递增(arr [i] / arr [j]) 。最后,打印获得的结果。

时间复杂度: O(N 2 )
辅助空间: O(N)

高效的方法:可以基于以下观察来优化上述方法:

请按照以下步骤解决问题:

  • 初始化一个数组,例如freq [] ,以存储数组元素的频率。
  • 初始化一个数组,例如preFreq [] ,以存储count []数组的前缀和。
  • preFreq [j] – preFreq [i]存储值在[i,j]范围内的数组元素的计数。
  • 找到数组中最大的元素,例如Max
  • [1,Max]范围内迭代。对于每个i值,使用preFreq []数组对值位于[i,j]范围内的数组元素进行计数,其中ji的倍数,然后将结果以frequency [i] *(preFreq [j – 1] – preFreq [j – i – 1])*(j / i – 1)
  • 最后,打印获得的结果。

下面是上述方法的实现:

C++
// C++ program to implement
// the above approach
#include 
using namespace std;
 
// Stores the maximum value of
// an array element
const int N = 3e5;
 
// Function to find the sum of
// floor(a[i]/a[j]) of all pairs (i, j)
void getFloorSum(int arr[], int n)
{
    // Stores frequency of
    // array element
    int freq[N] = { 0 };
 
    // Stores prefix sum
    // array of frequency[]
    int preFreq[N] = { 0 };
 
    // Traverse the array
    for (int i = 0; i < n; i++) {
 
        // Update frequency
        // of arr[i]
        freq[arr[i]]++;
    }
 
    // Compute the prefix sum
    // of frequency[]
    for (int i = 1; i < N; i++) {
        preFreq[i]
            = preFreq[i - 1] + freq[i];
    }
 
    // Stores the sum of floor(a[i]/a[j])
    // of all pairs (i, j)
    int ans = 0;
 
    // Iterate over the range [1, Max]
    for (int i = 1; i <= N; i++) {
 
        // Find the count of numbers in
        // the range [i * K, i * (K + 1))
        // and update the result
        for (int j = i; j <= N; j += i) {
 
            // Stores count of numbers
            // in range[j - i - 1, j - 1]
            int X = (preFreq[j - 1]
                     - preFreq[j - i - 1]);
 
            // Update ans
            ans += X * (j / i - 1) * freq[i];
        }
    }
 
    // Print the answer
    cout << ans;
}
 
// Driver Code
int main()
{
 
    // Given array
    int arr[] = { 1, 2, 3 };
 
    // Stores the size of array
    int n = sizeof(arr) / sizeof(arr[0]);
 
    getFloorSum(arr, n);
 
    return 0;
}


Java
// Java program to implement
// the above approach
import java.util.*;
class GFG{
 
// Stores the maximum value of
// an array element
static int N = (int) 3e5;
 
// Function to find the sum of
// Math.floor(a[i]/a[j]) of all pairs (i, j)
static void getFloorSum(int arr[], int n)
{
   
    // Stores frequency of
    // array element
    int freq[] = new int[N];
 
    // Stores prefix sum
    // array of frequency[]
    int preFreq[] = new int[N];
 
    // Traverse the array
    for (int i = 0; i < n; i++)
    {
 
        // Update frequency
        // of arr[i]
        freq[arr[i]]++;
    }
 
    // Compute the prefix sum
    // of frequency[]
    for (int i = 1; i < N; i++)
    {
        preFreq[i]
            = preFreq[i - 1] + freq[i];
    }
 
    // Stores the sum of Math.floor(a[i]/a[j])
    // of all pairs (i, j)
    int ans = 0;
 
    // Iterate over the range [1, Max]
    for (int i = 1; i < N; i++)
    {
 
        // Find the count of numbers in
        // the range [i * K, i * (K + 1))
        // and update the result
        for (int j = i; j < N; j += i)
        {
 
            // Stores count of numbers
            // in range[j - i - 1, j - 1]
            int X = (preFreq[j - 1]
                     - preFreq[Math.abs(j - i - 1)]);
 
            // Update ans
            ans += X * (j / i - 1) * freq[i];
        }
    }
 
    // Print the answer
    System.out.print(ans);
}
 
// Driver Code
public static void main(String[] args)
{
 
    // Given array
    int arr[] = { 1, 2, 3 };
 
    // Stores the size of array
    int n = arr.length;
    getFloorSum(arr, n);
}
}
 
// This code is contributed by shikhasingrajput


Python3
# Python3 program to implement
# the above approach
 
# Stores the maximum value of
# an array element
N = 10**5
 
# Function to find the sum of
# floor(a[i]/a[j]) of all pairs (i, j)
def getFloorSum(arr, n):
   
    # Stores frequency of
    # array element
    freq = [ 0  for i in range(N + 1)]
 
    # Stores prefix sum
    # array of frequency[]
    preFreq = [ 0  for i in range(N + 1)]
 
    # Traverse the array
    for i in range(n):
 
        # Update frequency
        # of arr[i]
        freq[arr[i]] += 1
 
    # Compute the prefix sum
    # of frequency[]
    for i in range(1, N):
        preFreq[i] = preFreq[i - 1] + freq[i]
 
    # Stores the sum of floor(a[i]/a[j])
    # of all pairs (i, j)
    ans = 0
 
    # Iterate over the range [1, Max]
    for i in range(1, N + 1):
 
        # Find the count of numbers in
        # the range [i * K, i * (K + 1))
        # and update the result
        for j in range(i, N + 1, i):
 
            # Stores count of numbers
            # in range[j - i - 1, j - 1]
            X = (preFreq[j - 1] - preFreq[j - i - 1])
 
            # Update ans
            ans += X * (j // i - 1) * freq[i]
 
    # Prthe answer
    print(ans)
 
# Driver Code
if __name__ == '__main__':
 
    # Given array
    arr = [1, 2, 3]
 
    # Stores the size of array
    n = len(arr)
 
    getFloorSum(arr, n)
 
# This code is contributed by mohit kumar 29


C#
// C# program to implement
// the above approach
using System;
 
class GFG{
 
// Stores the maximum value of
// an array element
static int N = (int)3e5;
 
// Function to find the sum of
// Math.Floor(a[i]/a[j]) of all
// pairs (i, j)
static void getFloorSum(int []arr, int n)
{
     
    // Stores frequency of
    // array element
    int []freq = new int[N];
 
    // Stores prefix sum
    // array of frequency[]
    int []preFreq = new int[N];
 
    // Traverse the array
    for(int i = 0; i < n; i++)
    {
         
        // Update frequency
        // of arr[i]
        freq[arr[i]]++;
    }
 
    // Compute the prefix sum
    // of frequency[]
    for(int i = 1; i < N; i++)
    {
        preFreq[i] = preFreq[i - 1] + freq[i];
    }
 
    // Stores the sum of Math.Floor(a[i]/a[j])
    // of all pairs (i, j)
    int ans = 0;
 
    // Iterate over the range [1, Max]
    for(int i = 1; i < N; i++)
    {
         
        // Find the count of numbers in
        // the range [i * K, i * (K + 1))
        // and update the result
        for(int j = i; j < N; j += i)
        {
             
            // Stores count of numbers
            // in range[j - i - 1, j - 1]
            int X = (preFreq[j - 1] -
                     preFreq[Math.Abs(j - i - 1)]);
 
            // Update ans
            ans += X * (j / i - 1) * freq[i];
        }
    }
     
    // Print the answer
    Console.Write(ans);
}
 
// Driver Code
public static void Main(String[] args)
{
     
    // Given array
    int []arr = { 1, 2, 3 };
     
    // Stores the size of array
    int n = arr.Length;
     
    getFloorSum(arr, n);
}
}
 
// This code is contributed by shikhasingrajput


输出:
9

时间复杂度: O(N + M * log(log(M)),其中M是最大的数组元素
辅助空间: O(M)