【问题标题】:Getting factors of a number with least sum in O(1)获取 O(1) 中总和最小的数的因数
【发布时间】:2017-08-24 07:20:43
【问题描述】:

我正在尝试找到 O(1) 中总和最小的数字的因子对。

解释如下:

If number is 100. Then all the possible pairs are :

1    X  100
2    X  50
4    X  25
5    X  20
10   X  10
20   X  5
25   X  4
50   X  2
100  X  1

这里总和最小的一对是 10,10,这显然是中间的一对

Similarly if number is 12 then pairs are as follows

1  X  12
2  X  6
3  X  4
4  X  3
6  X  2
12 X  1

这里需要的对是 3,4 或 4,3。

If a number has 'p' pairs then the required one is always ceil(p/2).

如果给定的数字是一个完美的正方形,那么任务就很简单了。这对只是sqrt(number),sqrt(number).

如果不是,那么这对将是ceil(sqrt(number)),number/ceil(sqrt(number))

<b>given that ceil(sqrt(number)) is a factor of number</b>

immediate factor neighbour of sqrt(number):

例如考虑“6”。 6 不是一个完美的正方形。

sqrt(6) 的 ceil 是 3,3 是 6 的因数。所以需要的对是 3,6/3=2

Now consider 102. All pairs are :

1  *  102.0
2  *  51.0
3  *  34.0
6  *  17.0
17  *  6.0
34  *  3.0
51  *  2.0
102 *  1

这里需要的对是 17,6 或 6,17。 Here ceil(sqrt(102)) is 11。 11 的直接因子邻居是 17 或 6。<b>Now this is what we actually find.</b>

我们如何找到直接因子邻居?

这是我的 O(n) 实现:

import math

l = []
n = int(input())
for i in range(1, n + 1):
    if n % i is 0:
        l.append(i)
middle = l[math.ceil(len(l) / 2)]
print("Required pair is ", middle, ",", n / middle)

【问题讨论】:

  • java 标签有什么用?
  • 对于任何整数?素数呢?
  • 它可以在 O(sqrt(n)) 中轻松解决,并且在 for 循环中获得最大除数
  • 究竟是什么让您认为 O(1) 可能?
  • 重要提示:寻找最接近 sqrt(n) 的除数实际上并没有帮助,因为我们不知道在 O(1) 中这样做。如果可以的话,我们将能够轻松地进行整数分解。更多信息在这里:math.stackexchange.com/questions/2376860/closest-divisor

标签: python algorithm math data-structures mathematical-optimization


【解决方案1】:

这里证明了找到该对必须至少与整数分解一样难(这意味着没有已知的 O(1) 算法):

如果我们从一个数字 N 开始并得到最小和的对,如图所示,除数最接近 sqrt(N),所以只有 2 种可能性:
1. 对是 1 - N,这意味着 N 是素数。这是微不足道的情况。
2. 我们发现了一些非平凡的除数 k。这意味着我们可以对 k 和 N/k 依次应用该算法,最终有效地找到所有素因数。

【讨论】:

    【解决方案2】:

    我也只能想到一个O(sqrt(n))的方法

    from math import sqrt, ceil
    
    m = 200
    
    for i in range(ceil(sqrt(m)), 0, -1):
        if m % i == 0:
            print(i, int(m / i))
            break
    

    我们有 10、20 个

    我们知道

    (a - b)^2 >= 0
    

    然后我们得到了

    a^2 + b^2 >= 2ab
    

    对于我们的案例

    x + m/x
    

    我们有

    x + m/x >= 2sqrt(m)
    

    所以我们得到了min(sum(x + m/x))的边界,min sum应该是由非常接近sqrt(m)的两个因子产生的;后面的数学问题是 x + m/x 函数,当 x = sqrt(m) 时, sum(x + m/x) 是最小的,但是由于我们需要 x 和 m/x 都是整数,所以我们应该尝试找到最接近 sqr(m) 的那些。

    【讨论】:

      【解决方案3】:

      不是O(n),但您可以使用以下程序降低时间复杂度

      from math import *
      
      val = floor(sqrt(n))
      l2 = []
      for i in range(val,n):
          if n%i == 0:
              l2.extend([i,n//i])
              break
      
      print(l2)
      

      这里我们基本上是在计算数字的平方根,并检查它是否是给定输入的一个因子。我们递增 1,直到找到第一个因子。该因子和所得商的对具有最小的和。

      两个程序的速度比较

      from math import *
      from time import time
      
      n = 1120304
      
      t0 = time()
      l = []
      for i in range(1, n + 1):
          if n % i is 0:
              l.append(i)
      
      middle = l[math.ceil(len(l) / 2)]
      # print("Required pair is ", middle, ",", n / middle)
      
      t1 = time()
      val = floor(sqrt(n))
      l2 = []
      for i in range(val,n):
          if n%i == 0:
              l2.extend([i,n//i])
              break
      
      t2 = time()
      
      t1-t0 # 0.1386280059814453
      t2-t1 # 0.009765148162841797
      

      【讨论】:

      • 这是一个 O(sqrt(n)) 解决方案,并不是 OP 真正要求的。
      • @TheJavatar,我知道。我在答案中提到了时间减少而不是O(1)
      【解决方案4】:

      我不认为这个问题是一个新问题。我看过一些类似的问题 从多年前开始,但从未见过O(1) 解决方案。

      所以让我们面对现实吧,O(sqrt(n)) 可能是最好的情况。

      【讨论】:

      • 应该是对的。看看李梦洛的回答。它的复杂度低于 O(sqrt(n))
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-27
      • 2021-07-20
      • 1970-01-01
      • 1970-01-01
      • 2012-08-16
      • 1970-01-01
      • 2019-04-28
      相关资源
      最近更新 更多