Php 格雷码生成-n位格雷码

Php 格雷码生成-n位格雷码,php,algorithm,gray-code,Php,Algorithm,Gray Code,这个问题是由hackerrank提出的,我得到了解决方案,但在最后的测试用例中,解决方案中有一个问题 问题如下 1 <= $n <= 65 输出 1 11 10 111 101 100 1010 1011 1001 1000 下面是2位序列(n=2) 输出 1 11 10 111 101 100 1010 1011 1001 1000 下面是3位序列(n=3) 输出 1 11 10 111 101 100 1010 1011 1001 1000 下面是4位序

这个问题是由hackerrank提出的,我得到了解决方案,但在最后的测试用例中,解决方案中有一个问题

问题如下

1 <= $n <= 65
输出

1
11 10
111 101 100
1010 1011 1001 1000
下面是2位序列(n=2)

输出

1
11 10
111 101 100
1010 1011 1001 1000
下面是3位序列(n=3)

输出

1
11 10
111 101 100
1010 1011 1001 1000
下面是4位序列(n=4)

输出

1
11 10
111 101 100
1010 1011 1001 1000
解决方案示例

以下是从2位格雷码列表生成3位格雷码列表的步骤

  • L1={00,01,11,10}(2位格雷码列表)
  • L2={10,11,01,00}(与L1相反)
  • 在L1的所有条目前面加上“0”前缀,L1变成{000,001,011,010}
  • 在L2的所有条目前面加上'1',L2变成{110,111,101,100}
  • 连接L1和L2,我们得到{000,001,011,010,110,111,101, 100}
下面给出了第一个解决方案。(基于上面的解决方案示例)

但下面给出的解决方案在22,23个数字之后将不起作用。 发生内存分配错误

<?php

$input = 2;

$list_array = ["0","1"];
$reverse_array = array_reverse($list_array);

for($i = 1; $i < $input; $i++ )
{
    for($j = 0; $j < sizeof($list_array); $j++)
    {
        $list_array[$j] = "0".$list_array[$j];
    }

    for($k = 0; $k < sizeof($reverse_array); $k++)
    {
        $reverse_array[$k] = "1".$reverse_array[$k];
    }

    $list_array = array_merge($list_array,$reverse_array);
    $reverse_array = array_reverse($list_array);
}

for($l = sizeof($list_array) - $input; $l < sizeof($list_array); $l++)  
{
    print_r($list_array[$l]);
    echo "<br />";
}

?>

下面给出了第二种解决方案

这一解决方案将持续到63岁。63之后,将显示超时错误

当64位php在64位操作系统上运行时,这将一直持续到63。如果它是在64位操作系统上运行的32位php,那么它在31位之后将无法工作

<?php

    $n = 59;

    $intial = pow(2, $n) - $n;

    $length = pow(2, $n) - 1;

    for($i= $intial; $i <= $length; $i++)
    {
        $decimal = ($i >> 1) ^ $i;
        print_r(decbin($decimal));
        echo "<br />";
    }
?>

请帮我找到这个解决方案

问题:如何解决上述问题,包括$n=64和$n=65


参考资料:

这应该适合您:

<?php

print_r( getResult( 4 ) );

function getResult ( $n ) {
    $result = [];
    for ( $i = 0; $i < $n; $i++ ) {
        $result[] = arr_xor(
          str_split( str_pad( str_pad( strtr( decbin($n - $i - 1), '01', '10' ), (int)ceil(log($n - $i - 1, 2)), '0', STR_PAD_LEFT ), $n, '1', STR_PAD_LEFT ) ),
          str_split( '0' . str_pad( substr( str_pad( strtr( decbin($n - $i - 1), '01', '10' ), (int)ceil(log($n - $i - 1, 2)), '0', STR_PAD_LEFT ), -1-(int)ceil(log($n - $i - 1, 2)), -1), $n - 1, '1', STR_PAD_LEFT ) )
        );
    }
    return $result;
}

function arr_xor( $a, $b ) {
    $result = [];
    for ( $i = 0; $i < count( $a ); $i++ )
        $result[] = (int)$a[$i] ^ (int)$b[$i];
    return implode( '', $result );
}

另一个答案类似于@paulpro,这与我在第二个解决方案中应用的想法相同<代码>($i>>1)^$i

<?php

$n = 65;

for ( $i = 0; $i < $n; $i++ ) 
{
    $decimal = decbin($n - $i - 1);

    $replace = strtr( $decimal, '01', '10' );

    $cast = (int)ceil(log($n - $i - 1, 2));

    $padding = str_pad( $replace , $cast , '0', STR_PAD_LEFT );

    $a_string = str_pad( $padding, $n, '1', STR_PAD_LEFT );

    //shifting the bit to right
    $substring = substr( $a_string , 0 , -1);
    $b_string = str_pad( $substring , $n, '0', STR_PAD_LEFT );

    $a = str_split( $a_string );
    $b = str_split( $b_string );

    for ( $j = 0; $j < count( $a ); $j++ )
    {
        print_r((int)$a[$j] ^ (int)$b[$j]);
    }

    echo "\n";
}

?>


哪里有问题?你在解决什么问题?这些“输出”是什么意思?我想上面已经详细解释过了,n位的输出是最后n位。所以你想用2^64项进行输出吗?是的@MBo想得到比2^64更好的解决方案,请告诉我。@MBo我相信他只想要最后的
$n
$n位格雷码,所以对于
$n=65
应该有65行输出,即使有
2^65
格雷码。您能解释一下
getResult()中两个参数的过程吗
function?@JeesKDenny第一个参数是包含
2**n-n+i
位的数组,第二个参数是包含
(2**n-n+i)>>1
位的数组。在MAX_INT_SIZE下为整数生成这些数组的方法要简单得多,但由于我希望它能在
64
32
以上工作,所以我使用了字符串操作。@JeesKDenny您可能最好只使用类似的方法,并且使用它可以比使用数组的答案做得更进一步,但我不想使用它,因为它假设您已经拥有
gmp
扩展,或者愿意并且能够编译并包含它。我已经浏览了这个库。但我对不使用任何图书馆很感兴趣。谢谢你的澄清。让我看一下@保普