📌  相关文章
📜  从数组中计算三元组,使得 a[j] – a[i] ≤ a[k] – a[j] ≤ 2 * (a[j] – a[i])

📅  最后修改于: 2022-05-13 01:56:05.988000             🧑  作者: Mango

从数组中计算三元组,使得 a[j] – a[i] ≤ a[k] – a[j] ≤ 2 * (a[j] – a[i])

给定一个大小为N的数组arr[] ,由不同的元素组成,任务是计算三元组的数量,使得(arr[j] – arr[i]) ≤ (arr[k] – arr[j]) ≤ 2 * (arr[j] – arr[i])arr[i] < arr[j] < arr[k] ( 1 ≤ i, j, k ≤ N并且它们中的每一个都应该是不同的)。

例子:

朴素方法:最简单的方法是生成所有可能的三元组,并为每个三元组检查它是否满足给定条件。

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

高效方法:上述方法可以通过二分搜索进行优化。请按照以下步骤解决问题:

  • 对数组arr[]进行排序。
  • 初始化一个变量,比如ans0,以存储三元组的数量。
  • 使用变量i迭代范围[1, N]并执行以下步骤:
    • 使用变量j[i+1, N]范围内迭代并执行以下步骤:
      • X初始化为arr[j] – arr[i]
      • 使用 lower_bound 找到arr[j]+X的下限并将其索引存储在变量l中。
      • 类似地,使用默认函数upper_bound 找到arr[j] + 2×X的上限,并将其索引存储在变量r中。
      • rl添加到变量ans中。
  • 执行上述步骤后,打印ans作为答案。

下面是上述方法的实现:

C++
// C++ program for the above approach
#include 
using namespace std;
int countTriplets(int arr[], int N)
{
    // Sort the array
    sort(arr, arr + N);
 
    // Stores count of triplets
    int l, r, i, j, ans = 0;
 
    // Iterate over the range [1, N]
    for (i = 0; i < N; i++) {
        // Iterate over the range [i+1, N]
        for (j = i + 1; j < N; j++) {
            // Required difference
            int x = arr[j] - arr[i];
 
            // Find lower bound of arr[j] + x
            // and upper bound of arr[j] + 2*x
            l = lower_bound(arr, arr + N, arr[j] + x) - arr;
            r = upper_bound(arr, arr + N, arr[j] + 2 * x)
                - arr;
 
            // Adjust the indexing of arr[j]+2*r
            if (r == N || arr[r] != arr[j] + 2 * x)
                r -= 1;
 
            // From l to r, count number of
            // triplets by using arr[i] and arr[j]
            ans += r - l + 1;
        }
    }
    // return main ans
    return ans;
}
// Driver code
int main()
{
    int arr[] = { 1, 2, 3 };
    int N = sizeof(arr) / sizeof(arr[0]);
    int ans = countTriplets(arr, N);
    cout << ans;
 
    return 0;
}


Java
// Java program for the above approach
import java.util.Arrays;
 
class GFG{
     
public static int countTriplets(int arr[], int N)
{
     
    // Sort the array
    Arrays.sort(arr);
     
    // Stores count of triplets
    int l, r, i, j, ans = 0;
 
    // Iterate over the range [1, N]
    for(i = 0; i < N; i++)
    {
         
        // Iterate over the range [i+1, N]
        for(j = i + 1; j < N; j++)
        {
             
            // Required difference
            int x = arr[j] - arr[i];
 
            // Find lower bound of arr[j] + x
            // and upper bound of arr[j] + 2*x
            l = lower_bound(arr, 0, arr.length - 1,
                                        arr[j] + x);
            r = upper_bound(arr, 0, arr.length - 1,
                                    arr[j] + 2 * x);
 
            // Adjust the indexing of arr[j]+2*r
            if (r == N || arr[r] != arr[j] + 2 * x)
                r -= 1;
 
            // From l to r, count number of
            // triplets by using arr[i] and arr[j]
            ans += r - l + 1;
        }
    }
 
    // Return main ans
    return ans;
}
 
public static int upper_bound(int[] arr, int low,
                              int high, int X)
{
     
    // Base Case
    if (low > high)
        return low;
 
    // Find the middle index
    int mid = low + (high - low) / 2;
 
    // If arr[mid] is less than
    // or equal to X search in
    // right subarray
    if (arr[mid] <= X)
    {
        return upper_bound(arr, mid + 1, high, X);
    }
 
    // If arr[mid] is greater than X
    // then search in left subarray
    return upper_bound(arr, low, mid - 1, X);
}
 
public static int lower_bound(int[] arr, int low,
                              int high, int X)
{
     
    // Base Case
    if (low > high)
    {
        return low;
    }
 
    // Find the middle index
    int mid = low + (high - low) / 2;
 
    // If arr[mid] is greater than
    // or equal to X then search
    // in left subarray
    if (arr[mid] >= X)
    {
        return lower_bound(arr, low, mid - 1, X);
    }
 
    // If arr[mid] is less than X
    // then search in right subarray
    return lower_bound(arr, mid + 1, high, X);
}
 
// Driver code
public static void main(String args[])
{
    int arr[] = { 1, 2, 3 };
    int N = arr.length;
    int ans = countTriplets(arr, N);
     
    System.out.println(ans);
}
}
 
// This code is contributed by gfgking


Python3
# Python3 program for the above approach
 
 
# Import library to apply
# binary search and find bound
from bisect import bisect_left
 
 
# Function to count triplets
# from an array that satisfies
# the given conditions
def countTriplets(arr, N):
 
    # Sort the array
    arr.sort()
     
    # Stores count of triplets
    ans = 0
 
    # Iterate over the range [1, N]
    for i in range(N):
 
        # Iterate over the range [i+1, N]
        for j in range(i+1, N):
 
            # Required difference
            x = arr[j]-arr[i]
 
            # Find lower bound of arr[j] + x
            # and upper bound of arr[j] + 2*x
            l = bisect_left(arr, arr[j] + x)
            r = bisect_left(arr, arr[j] + 2*x)
 
            # Adjust the indexing of arr[j]+2*r
            if r == N or arr[r] != arr[j]+2*x:
                r -= 1
 
            # From l to r, count number of
            # triplets by using arr[i] and arr[j]
            ans += r-l+1
 
    # return main ans
    return ans
 
 
# Driver Code
if __name__ == "__main__":
 
    # Given Input
    arr = [1, 2, 3]
    N = len(arr)
 
    # Function Call
    ans = countTriplets(arr, N)
    print(ans)


C#
// C# program for the above approach
using System;
class GFG {
     
    static int countTriplets(int[] arr, int N)
    {
          
        // Sort the array
        Array.Sort(arr);
          
        // Stores count of triplets
        int l, r, i, j, ans = 0;
      
        // Iterate over the range [1, N]
        for(i = 0; i < N; i++)
        {
              
            // Iterate over the range [i+1, N]
            for(j = i + 1; j < N; j++)
            {
                  
                // Required difference
                int x = arr[j] - arr[i];
      
                // Find lower bound of arr[j] + x
                // and upper bound of arr[j] + 2*x
                l = lower_bound(arr, 0, arr.Length - 1,
                                            arr[j] + x);
                r = upper_bound(arr, 0, arr.Length - 1,
                                        arr[j] + 2 * x);
      
                // Adjust the indexing of arr[j]+2*r
                if (r == N || arr[r] != arr[j] + 2 * x)
                    r -= 1;
      
                // From l to r, count number of
                // triplets by using arr[i] and arr[j]
                ans += r - l + 1;
            }
        }
      
        // Return main ans
        return ans;
    }
      
    static int upper_bound(int[] arr, int low,
                                  int high, int X)
    {
          
        // Base Case
        if (low > high)
            return low;
      
        // Find the middle index
        int mid = low + (high - low) / 2;
      
        // If arr[mid] is less than
        // or equal to X search in
        // right subarray
        if (arr[mid] <= X)
        {
            return upper_bound(arr, mid + 1, high, X);
        }
      
        // If arr[mid] is greater than X
        // then search in left subarray
        return upper_bound(arr, low, mid - 1, X);
    }
      
    static int lower_bound(int[] arr, int low,
                                  int high, int X)
    {
          
        // Base Case
        if (low > high)
        {
            return low;
        }
      
        // Find the middle index
        int mid = low + (high - low) / 2;
      
        // If arr[mid] is greater than
        // or equal to X then search
        // in left subarray
        if (arr[mid] >= X)
        {
            return lower_bound(arr, low, mid - 1, X);
        }
      
        // If arr[mid] is less than X
        // then search in right subarray
        return lower_bound(arr, mid + 1, high, X);
    }
 
  static void Main() {
    int[] arr = { 1, 2, 3 };
    int N = arr.Length;
    int ans = countTriplets(arr, N);
      
    Console.WriteLine(ans);
  }
}
 
// This code is contributed by divyeshrabadiya07.


Javascript


输出
1

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