在字符串中找到完美的正方形

时间:2013-02-14 10:22:19

标签: c++ python algorithm

一个完美的正方形是二进制的,一些位用“?”代替例如1 ??,数字将是4.(或1 ???? 000 ??? 0000)

我需要找到完美的方块。(只会有这样的数字)

字符串中的'?'是n

要找到这个数字我正在做的是迭代2 ** n个数字(111,110,101,100)并检查它是否是一个完美的正方形。我正在使用以下功能来检查它是否是一个完美的正方形。

bool issqr(int n){
   int d=(int)(sqrt(n));
   if(d*d==n) return true;
   else return false;
}

即使在python中我做了它,也需要花费很多时间,所以我只使用位操作来转换到C ++来填充2 ** n个数字(这比python版本快得多)

但如果数字超过64位

,则会失败

如何避免这个问题?如果一个数字说120位,我怎么能做同样的事情。

(10100110 ??? 1→1→01→1→011000?1100?00101000→1→11001101100110001010111?0,α1≠0110&#601​​10&01?1100?1?0110?1?10111?01?0111000 ?10 -4 101?01)

4 个答案:

答案 0 :(得分:3)

您应该首先考虑改进算法,而不是用C ++重写。最低的答案是原始值的平方根,所有'?'替换为0向上舍入,最高可能的答案是模式的平方根,其中'?'替换为1向下舍入。找到这两个值,迭代它们,平方并检查模式。

这两者都更快,因为你正在迭代更少的数字并且因为你没有计算循环中的任何平方根:平方更容易。

您无需比较字符串来检查匹配项:

mask = int(pattern.replace('0', '1').replace('?', '0'), 2)
test = int(pattern.replace('?', '0'), 2)

def is_match(n):
    return (n&mask)==test

所以把它们放在一起:

def int_sqrt(x):
    if x < 0:
        raise ValueError('square root not defined for negative numbers')
    n = int(x)
    if n == 0:
        return 0
    a, b = divmod(n.bit_length(), 2)
    x = 2**(a+b)
    while True:
        y = (x + n//x)//2
        if y >= x:
            return x
        x = y

def find_match(pattern):
    lowest = int(pattern.replace('?', '0'), 2)
    highest = int(pattern.replace('?', '1'), 2)
    mask = int(pattern.replace('0', '1').replace('?', '0'), 2)
    lowsqrt = int_sqrt(lowest)
    if lowsqrt*lowsqrt != lowest:
            lowsqrt += 1
    highsqrt = int_sqrt(highest)
    for n in range(lowsqrt, highsqrt+1):
        if (n*n & mask)==lowest:
            return n*n

print(find_match('1??1??1'))
print(find_match('1??0??1'))
print(find_match('1??????????????????????????????????????????????????????????????????????1??0??1'))

输出:

121
81
151115727461209345152081

N.B。这仅适用于Python 3.x,最后一个测试将在Python 2.x中溢出range

答案 1 :(得分:2)

根据我的理解,给定一个整数n,您试图找到匹配的正方形数字sq

  

2 n - 1&lt; sq&lt; 2 n + 1 - 1

这个条件是“我的号码必须有表格1 ????”的数学翻译哪里有n“?”。

首先,您可以注意到,如果n是偶数,则数字2 n 是一个完美的正方形并且符合您的条件(二进制,数字为1000 ... 000 - n neroes - )。

如果n不均匀(比如n = 2.p + 1),则2 n + 1 是一个完美的平方((2 p + 1 2 )。计算以下数字将为您提供一个完美的方块:

  

(2 p + 1 - 1) 2

为了满足第一个不等式,p必须满足:

  

2 n - 1&lt; (2 p + 1 - 1) 2

然后

  

0&lt; 2 n + 1 - 2 p + 2 + 1 - 2 n + 1,

最后,

  

2 n + 2 - 2 p + 2 &gt; 0
  或
  2 2p -2 p + 1 + 1> 0

如果我们考虑将p与f(p)匹配的函数,那么:

  

f(p)= 2 2p - 2 p + 1 + 1

此函数是为每个正实数定义的,并且严格增加。此外,f(0)= 0.最后,p > 0时满足初始条件! 对于p = 0 - 或n = 1 - ,问题没有有效的解决方案。

答案 2 :(得分:0)

你不需要遍历所有2 ** n个数字来找到完美的正方形,实际上你只需要一个小数平方运算:

假设您有整数n,并且您想要找到小于或等于n的最大完美平方,我们称之为m。 然后:

d = (int)sqrt(n);
m = d*d;

说明:

假设存在大于m的完美平方m',这意味着存在整数d',使得:d'> d和d'* d'= m'。

但是d'> = d + 1且(d + 1)*(d + 1)>那么m'&gt; n与我们的要求m'&lt; = n。

相矛盾

现在回答你的问题:

为了找到完美的方块,只需将“1”改为“1”即可。并找到完美的方形,如果它符合你的字符串你得到了你正在寻找的数字,如果没有改变就足够“?”从msb到“0”,以便得到的数字小于或等于你刚刚找到的完美方形,并继续前进,直到你找到完美的方形或用完选项。

答案 3 :(得分:-1)

您的操作可能会返回一个对整数来说太大的东西...... http://www.cplusplus.com/doc/tutorial/variables/