【问题标题】:given a number p , find two elements in array whose product = P给定一个数字 p ,在数组中找到 product = P 的两个元素
【发布时间】:2019-06-18 01:14:38
【问题描述】:

我正在寻找解决方案:

Given a array and a number P , find two numbers in array whose product equals P.

寻找比 O(n*2) 更好的解决方案。我可以使用额外的空间或其他数据结构。任何帮助表示赞赏?

【问题讨论】:

  • 这听起来真的像家庭作业。
  • 对数字的类型有什么限制吗(比如只限整数、只限正整数等)?
  • 数量不限。
  • 如果对数字没有限制(除了可能是实数),存在解的可能性接近于零,特别是如果一个或多个数字是浮点近似值。经典论文:docs.sun.com/source/806-3568/ncg_goldberg.html

标签: algorithm data-structures


【解决方案1】:

遍历数组,并将元素添加到 Hashtable。对于添加的每个元素 x,检查 P/x 是否已存在于哈希表中 - 如果存在,则 x 和 P/x 是您的解决方案之一。这将是您将获得的最佳效果。

【讨论】:

  • @Michael - 这有关系吗?授予的 P/x 可能不完全位于 Hashtable 中的元素上 - 如果这会造成问题,则对数组进行排序和二进制搜索以找到最接近 P/x 的元素并将该元素乘以 x 以检查 P 可能是更好的选择。
  • 您的答案当然是正确的。但是,必须在实现中进行某种程度的量化/合并才能使其正常工作。再说一次,这种量化对于 O(n^2) 算法也是必要的。请原谅在深夜发布的 cmets。 :)
【解决方案2】:

您可以尝试滑动窗口的方法。首先对所有数字进行递增排序,然后使用两个整数beginend 来索引当前这对数字。将begin 初始化为0,将end 初始化为最后一个位置。然后比较v[begin]v[end]P的乘积:

  • 如果相等,您就找到了答案。
  • 如果更低,一定要找更大的产品,向前移动begin
  • 如果更高,你必须找到更小的产品,将end向后移动。

这是一个实现了这个想法的 C++ 代码。由于排序,此解决方案为 O(n*log(n)),如果您可以假设数据已排序,那么您可以跳过 O(n) 解决方案的排序。

pair<int, int> GetProductPair(vector<int>& v, int P) {
  sort(v.begin(), v.end());
  int begin = 0, end = static_cast<int>(v.size()) - 1;
  while (begin < end) {
    const int prod = v[begin] * v[end];
    if (prod == P) return make_pair(begin, end);
    if (prod < P) ++begin;
    else --end;
  }
  return make_pair(-1, -1);
}

【讨论】:

  • 我直觉这可能找不到解决办法。
  • @pascal:这种技术是有效的,并且可以被证明。但是,在排序后执行此操作在复杂性方面没有用处。您可以简单地扫描项目并使用二进制搜索来查找互补操作数。总体复杂度仍然是 O(N Log N)。这种技术的优点是当数组已经排序时,可以实现线性时间。
  • 是的,你是对的。我正在考虑将begin 移动一次太远,并且不得不将其移回以尝试一对更大的end。但是在这个心理图像中,我忽略了数组也是在end 一侧排序的......
  • 这可能不适用于具有负数的数组?例如:v = [-8,-2,2,8] 和 p = 16。第一个 v[begin]*v[end] = -8*8 = -64 小于 16 所以我们继续增加开始.所以这样我们就会错过这对 (-8,-2)。
  • @anilkumar:是的。如果 P 为正且有负数,则排序后需要求解 2 个子问题。设 k 是第一个包含正数的索引。您需要解决子问题 [1..k-1] 与 [1..k-1],这可以通过(概念上)反转此范围并“忘记”它们的负号来完成,并且还解决子问题 [k ..n] vs [k..n] (以通常的方式)。如果 P 为负数,则原始算法的变体起作用:在 k-1 处开始 begin,当当前乘积 > P 时将其向后移动。无论哪种方式,都是 O(n) 时间, 不包括排序时间。
【解决方案3】:

这个只适用于整数: 将 P 分解为素数的乘积。通过将它们分成两组,您可以获得将 P 作为产品的对。现在您只需检查它们是否都存在于数组中,这是哈希表非常有用的地方。此外,在创建哈希表时,您还可以过滤重复值数组、大于 P 的值,甚至是 P 中不包含素因数的值。

【讨论】:

  • 好主意,虽然分解可能比 O(n²) 多一点。
  • @liori:不一定,如果你有一个预先计算好的素数列表,那么它就是 O(n)。
  • 是的,你是对的。尽管要存储分解任何 64 位整数所需的素数,但您需要约 0.8GB 的​​内存。无论如何,+1。
【解决方案4】:
  • 创建将在以下步骤中填充的哈希。
  • 逐一迭代数组的元素。说当前元素是 n
    • 如果数字 P 可以被 n 整除
      • 检查 n 是否为散列值之一。如果是,那么那个键、值就是我们正在寻找的两个数字,我们可以破解。
      • 如果 n 不在散列值中,则将 n,x 添加到散列中,其中 n*x = P
    • 如果数字 P 不能被 n 整除,则继续数组的下一个元素
  • 如果我们到达数组的末尾,那么数组中就没有这样两个乘积为 P 的数字

这个算法是 O(n)

【讨论】:

    【解决方案5】:

    1.在 O(nlogn) 时间内将数字排序到数组 A 中,删除所有零

    2.创建一个数组 B 使得 B[i] = P/A[I] 在 O(n) 时间内

    3.对于B中的每个B[k],在A中对该元素进行二分搜索,最坏情况下需要O(nlogn)时间

    如果元素 B[k] 存在于数组 A 中的位置 m,则 A[k] * A[m] = P 否则不存在这样的对

    总运行时间为O(nlogn)

    当然这在真机上可能会因为浮点错误而遇到困难

    【讨论】:

      【解决方案6】:
      public boolean factors_Of_Product_In_Array(int a[],int product,int factorsLimit)
      {
          int i = 0,count = 0;
          boolean flag = false;
      
          if(factorsLimit==0)
              flag = false;
      
          //If product value is zero - only verify if there is any '0' value in array
          else if(product==0)
          {
              for(i=0;i<a.length;i++)
              {
                  if(a[i]==0)
                      flag = true;
              }
          }
      
          //If product value is 1 - Verify at least factorsLimit number of 1's should be present in array
          else if(product==1)
          {
              for(i=0;i<a.length;i++)
              {
                  if(a[i]==0)
                      count=count+1;
              }
      
              if(count==factorsLimit)//Verifying if the number of 1's is equal to number of factors required
                  flag = true;
          }
      
          else
          {
              for(i=0; i<a.length && count!=factorsLimit ;i++)
              {
                  if(product%a[i]==0)
                  {
                      product = product/a[i];
                      count = count+1;
                      System.out.println(" "+a[i]+" ");
                  }
              }
      
          if(count==factorsLimit)
              flag = true;
          }
      
          return flag;
      }
      

      【讨论】:

        【解决方案7】:

        已更新以提供实现。

        O(n+P)解,忽略P等于0的情况。

        #include <stdio.h>
        #include <iostream>
        #include <vector>
        
        using namespace std;
        
        int main(){
            auto arr = new vector<int>();
            int P, numOfEle, ele;
        
            cout << "The number of elements to be entered: " << endl;
            cin >> numOfEle;
            cout << "Please enter the elements: " << endl;
            for (int i = 0; i < numOfEle; i++){
                cin >> ele;
                arr->push_back(ele);
            }
            cout << "Please enter P: " << endl;
            cin >> P;
        
        
            //O(n+P) solution, ignoring the case of P equal to 0
            bool* factorsInNeed = new bool[P];
            for (int i = 0; i < P; i++)
                factorsInNeed[i] = false;
            for (auto i : *arr){
                if (i != 0 && P/(double)i == P/i){ //if divisble
                    if (factorsInNeed[i]){
                        cout << "A solution: " << i << " & " << P/i << endl;
                        break;
                    }
                    factorsInNeed[P/i] = true;
                }
            }
        }
        

        【讨论】:

          【解决方案8】:

          这是我的镜头,它只比较任何因素一次

          P <- The Number
          theArray <- new array[theData]
          factors <- new array[]
          isFactor <- new map(init: false)
          factorCount <- 0
          i <- 0
          while i is in theArray
              num <- theArray[i]
              if (isFactor[num])
                  skip
              if num modulo P == 0
                  isFactor[num] <- true
                  j <- 0
                  while j is in factors
                      if factors[j] * num == P
                          return (num, factors[j])
                      j++
                  factors.push(num)
                  factorCount++
              i++
          

          【讨论】:

          • factors 里面有什么东西吗?
          【解决方案9】:

          不确定这是否是最好的解决方案,但它确实有效。你可以尝试优化一下。

          public class CombInput
              {
                  public int ID;
                  public string Value;
              }
          
            public List<string> GetCombinations(List<string> values)
                  {
          
                      List<CombInput> input = new List<CombInput>();
                     List<string> outputvalues = new List<string>();
                      int counter = 1;
                       foreach (String c in values)
                       {
                           input.Add(new CombInput { ID = counter, Value = c });
          
                           counter++;
                       }
                      var Output = from i in input
                                  select i;
          
                      string Final = Output.Select(query => query.Value).Aggregate((a, b) => a + "|" + b);
          
                      while (!Output.ToList().Exists(s=>s.Value.ToString()==Final))
                      {
                          var store = Output;  
                          var  Output1= 
                          (from o in Output
                                    from v in input
                                   where (v.ID < o.ID && !(store.Any(a=>a.Value==v.Value + "|" + o.Value)))
                                         select new CombInput { ID = v.ID, Value = v.Value + "|" + o.Value });
          
                          var Outputx = (from s in store select s)
                          .Concat
                          (from s in Output1.ToList() select s);
                          Output = Outputx;
                      }
          
          
                      foreach (var v in Output)
                          outputvalues.Add(v.Value);
                      return outputvalues.ToList();
                  }
          
           public List<string> GetProductCombinations(List<int> nums, int productCriteria)
                  {
                      List<string> input = (from i in nums
                                           select i.ToString()).ToList();
                      input = GetCombinations(input);
          
                      var O = from i in input
                              where i.Split('|').ToList().Select(x => Convert.ToInt32(x)).ToList().Aggregate((a, b) => a * b) == productCriteria
                              select i;
          
          
                      List<string> output=new List<string>();
                      foreach (string o in O)
                      {
                          output.Add(o);
                      }
                      return output;
                  }
          
          
           private void button1_Click(object sender, EventArgs e)
                  {
          
                       List<string> output = new List<string>();
                      List<int> nums = new List<int>();
                      int[] numsarr ={1,2,3,4,6,7,8,12};
                      nums = numsarr.ToList();
                      output = GetProductCombinations(nums, 12);
          }
          

          【讨论】:

            【解决方案10】:

            void PrintPairOfProduct(int arr[],int size,int k) {

                      int i,temp[MAX];
                       memset(temp,1,MAX);
                       for(i=0;i<size;++i)
                       {
                        if(k % arr[i] == 0 && temp[arr[i]] != -1 && temp[k/arr[i]] != -1)
                        {
                         if((temp[k/arr[i]] * arr[i]) == k)
                         {
                         printf("Product of %d * %d = %d",k/arr[i],arr[i],k);``
            
                         temp[k/arr[i]] = -1;
                         temp[arr[i]] = -1;
                        }
                        temp[arr[i]] = arr[i];
            

            }}

            【讨论】:

              【解决方案11】:
              #include<stdio.h>
              int main()
              {
               int arr[]={2,15,4,5,6,7};
               const int  c = 30;
               int i = 0,j=1;
               int num =0;
               while ( i<= 6 )
               {
                  num = arr[i] * arr[j];
                  if ( num == 30)
                  {
                     printf("Pairs[%d,%d]\t",arr[i],arr[j]);
                  }
                  if (j == 5 )
                  {
                     i = i+1;
                     j = i + 1;
                     if (j==6)
                     {
                        break;
                     }
                     else
                     {
                     continue;
                     }
                  }
                  j= j+1;
              
               }
              
              
               return 0;
              }
              

              【讨论】:

                猜你喜欢
                • 2016-02-15
                • 1970-01-01
                • 2016-03-16
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2011-06-19
                • 1970-01-01
                相关资源
                最近更新 更多