子阵列,其乘积等于N.

时间:2011-04-07 13:03:48

标签: algorithm

  

可能重复:
  Sub array that produces a given sum and product

给定一个数组,找到一个子数组,其中元素的乘积等于N. 这是我的尝试

P = 1
Make an another array arr1
for  i = 0 to n-1
  arr1[i] = P
  P *= arr1[i]
put elements, index of arr1 in hash table
for i = 0 to n-1
  search in hash table for P/arr1[i]
  if found
    return [i+1 ... index in hash table]

这是对的吗?任何其他更简单的解决方案。

4 个答案:

答案 0 :(得分:4)

它可以在O(n)时间和O(1)存储器中解决,只需要2个额外的指针和当前产品。想法是使用滑动窗口。保留两个指针,p1和p2。最初它们都指向数组的第一个元素,乘积等于1.虽然乘积小于n然后向右移动p2并在p2处逐个元素乘以。当你达到n或更多:如果product == n返回p1和p2,否则向右移动p1并重复它直到p2到达数组的末尾。

答案 1 :(得分:1)

你的解决方案基本上是合理的。它很简单并且具有O(n)时间复杂度(假设哈希表插入和查找都是O(1))。因为在最坏的情况下,任何解决方案都需要至少检查一次每个元素,O(n)就像你能得到的一样好。

关于分工有两个问题:

  1. 我认为P/arr1[i]表示N/arr1[i]
  2. 它是一个整数除法(在这种情况下你的解决方案是不正确的)还是浮点数(在这种情况下代码暴露于浮点问题)并不明显。要对此进行防范,您需要在搜索周围添加if声明,以确保N可以被arr1[i]整除。
  3. 另外,我认为你的索引可能搞砸了,但我现在没时间详细检查它。

答案 2 :(得分:1)

Artem Volkhin's answer建议的滑动窗口算法具有O(n)复杂度。

优点

  • 非常快 - O(n),单程。
  • 迭代总是向前指示 - 可以与链接列表一起使用。
  • 就地,记忆效率高。
  • 无计算开销 - 最好的情况是O(1)。

缺点

  • 所有数字都应该是> 1,因为它依赖于乘法随着我们向前移动第二个指针而增加的事实。

Python实现

def sliding_window(seq, n):   
    low,high=0,0              # Low index, High index
    cur_sum=seq[low]          
    while high<=len(seq):
        if cur_sum==n:        # Match found, return indices
            return low, high  
        elif cur_sum<n:       # Sum to low, increase high index
            high+=1
            cur_sum*=seq[high]
        else:
            cur_sum/=seq[low] # Sum to high, increase low index
            low+=1
     return None, None        # No match, Return

实施例

>>> ls=range(1,11)
>>> print ls
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
>>> 
>>> N=336     # 6*7*8
>>> print sliding_window(ls, N)
(5, 7)        # Indices

答案 3 :(得分:0)

(在c ++中):

// returns true if found and sub-array indices in low & high, false otherwise

bool findprod(int arr[], int size, int N, int& low, int& high)
{
  int prod = 1;
  for (low = high = 0; high < size; ++high) {
    prod *= arr[high];
    if (prod < N) continue;
    if (prod > N) 
      for (; prod > N && low <= high; ++low)
        prod /= arr[low];
    if (prod == N) break; // found
  }
  return high < size;
}

(与我看到的@Artem相同的解决方案)