C++ 选择距离最远的两个点之间距离小于等于L的三个点的方法

C++ 选择距离最远的两个点之间距离小于等于L的三个点的方法

问题陈述要求我们确定选择三个点的方式,其中最远的两个点之间的距离小于或等于L,一个正整数将作为输入给出。

在问题中,我们将得到一个在x轴上的不同点的数组和一个大于0的整数L。任务是找到距离最远的两个点之间距离小于或等于整数L的三个点的集合的数量。

注意:给出的点集可以按照数组中给定的任意顺序排列。

以下给出的示例可以更好地理解这个问题。

输入

a[] = {5, 6, 7, 8}
L=3

输出

4

解释:从给定数组中距离最远的三个点的集合,距离小于或等于三,如下:

{5, 6, 7},{5, 6, 8},{5, 7, 8}和{6, 7, 8}。

从未出现在一个集合中距离最远的点相隔超过三倍的情况。

由于点集可以以任何顺序排列,所以{5,6,7}和{5,7,6}被认为是相似的三个点集。

输入

a[] = {3, 5, 6, 9}
L=3

输出

1

说明:由于三元组的最远两点之间的距离最多只能为3,只有一个可能的三元组,即{3, 5, 6}。

我们可以用不同的方法解决上述问题。让我们从简单的方法到高效的解决方案来看如何解决这个问题。

方法1

这将是解决问题的基本策略。该方法的目标是检查在提供的数组中可能存在的每个三元组,并确定其最远点之间的距离是否小于或等于指定的L值。如果三元组的最远点之间的距离小于或等于L,则计数三元组,否则继续寻找其他三元组。这将为我们提供选择三个点的每个选项,其中最远点的距离小于或等于L。

按照以下步骤,我们可以在代码中实现这个方法:

  • 对给定数组进行排序,以便在给定数组中迭代时,我们可以检查每个可能的三元组,如a[i]<a[i+1]<a[i+2]。

  • 声明一个名为count的变量,用于计算最远点小于或等于L的可能三元组的数量。

  • 使用三个嵌套循环遍历整个数组,对每个可能的三元组进行遍历,第一个循环从x=0开始,第二个循环从y=x+1开始,第三个循环从z=y+1开始。

  • 如果我们找到任何满足a[z]-a[x]<=L的三元组,我们将计数增加1,并继续遍历数组以寻找下一个可能的三元组。

  • 遍历整个数组从i=0到i<array size-2,以检查所有可能的三元组,我们可以找到每种选择三个点的方式,其中最远的点<=L。

例子

//C++ code to find number of ways of choosing triplet

#include <bits/stdc++.h>

using namespace std;

//function to count the number of ways of choosing three points
int triplets(int a[], int N, int L){

   int count =0; //to count the total number of ways

   sort(a,a+N); //sorting the array using in-buit sort() function

   //iterating in the nested loops to check every triplet
   for(int x=0;x<N-2;x++){
      for(int y=x+1;y<N-1;y++){
         for(int z=y+1;z<N;z++){
            int furthest = a[z] - a[x];
            if(furthest<=L){ //if distance between the furthest points <=L
               count += 1; //increasing count by 1
            }
         }
      }
   }

   return count;  //return the possible number of ways satisfying the condition
}

int main()
{
   int a[] = {10, 2, 3, 7, 13, 9};
   int L=5;

   int N= sizeof(a)/sizeof(a[0]); //to calculate size of array

   cout<<"Total triplets possible : "<<triplets(a, N, L)<<endl;

   return 0;
}

输出

Total triplets possible : 3

时间复杂度:O(N^3),其中N是给定数组的大小。

空间复杂度:O(1),因为我们没有使用任何额外的空间。

方法2(高效方法)

上述朴素方法的高效解法是使用二分查找。我们将简单地在数组中从i=0到i<数组大小的范围内进行迭代。对于数组中的每个元素,我们将找到大于a[i]并且小于等于a[i]+L的点的数量。为了找到所有最远点之间的距离小于等于L的所有可能三元组,我们可以使用组合。
^nC_{r}=\frac{n!}{(n-r)!r!}其中n是大于a[i]并且小于等于a[i]+L的点的数量,r是2,因为我们希望选择两个点来构成可能的三元组。
因此,替换n和r的值,我们可以写成

三元组的数量 = 点的数量 * (点的数量 – 1)/2

使用这种方法,我们可以找到满足条件的每个点在数组中的可能三元组。

按照以下步骤在C++中实现此方法:

  • 我们将创建一个函数来计算可能三元组的数量。

  • 然后,对给定的数组进行排序以使用C++中的二分查找,使用sort()函数进行排序。

  • 遍历整个数组,从i=0到i<数组的大小-2,计算每个元素的可能三元组。

  • 对于每个元素a[i],使用C++中的upper_bound函数找到第一个大于a[i]+L的元素的索引,它返回指向范围内大于传入值的指针。

  • 为了找到大于a[i]并且小于等于L的点的数量,将大于a[i]+L的点的索引与i+1相减。

  • 如果大于a[i]并且小于等于L的点的数量大于或等于2,则可以使用上述推导出的公式计算最远点小于等于L的可能三元组的数量,即点的数量 * (点的数量 – 1)/2。

  • 计算给定数组中的每个元素,其中最远点之间的距离小于等于L的所有可能三元组。

例子

//C++ code to calculate number of possible ways to choose triplet using binary search
#include<bits/stdc++.h>

using namespace std;

//function to print the total triplets possible where distance
//between the furthest points <=L
int triplets(int a[], int N, int L)
{
   sort(a, a + N); //sort the array using sort() function

   int count = 0; //to count the number of ways possible


   for (int i = 0; i <= N-2; i++) {
       //using upper bound function to find the index greater than a[i]+L
     int index = upper_bound(a, a + N,a[i] + L) - a; 

      int x = index - (i + 1); //number of points

      if (x >= 2) {

         count += (x * (x - 1) / 2); 
      }
   }
   //return the total ways
   return count;
}

int main()
{
   int a[] = {4,7,3,9,8,10};
   int L = 6;

   int N = sizeof(a) / sizeof(a[0]); //to calculate the size of the array

   cout<<"Total triplets possible : "<<triplets(a, N, L)<<endl; //calling the function

   return 0;
}

输出

Total triplets possible: 16

时间复杂度:O(NlogN),其中N为数组的大小。

空间复杂度:O(1),因为没有使用额外的空间。

结论

阅读本文后,我希望你对这个问题的概念已经清楚了。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程