获得O(1)中总和最小的数的因子

时间:2017-08-24 07:20:43

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

我试图找到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))

given that ceil(sqrt(number)) is a factor of number

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. Now this is what we actually find.

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

这是我的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)

4 个答案:

答案 0 :(得分:4)

我也只能想到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)),最小和应该由非常接近sqrt(m)的两个因子产生;后面的数学问题是x + m / x函数,当x = sqrt(m)时,sum(x + m / x)最小化,但由于我们需要x和m / x都是整数,所以我们应该尝试找到最接近sqr(m)的那些。

答案 1 :(得分:4)

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

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

答案 2 :(得分:1)

不是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

答案 3 :(得分:1)

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

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