没有strrev

时间:2015-04-23 08:08:42

标签: php string

前一段时间,在求职面试中,我完成了使用strrev中使用来反转字符串

的任务。

我的第一个解决方案是这样的:

$s = 'abcdefg';
$temp = '';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
    $temp .= $s{$length - $i - 1};
}
var_dump($temp);
// outputs string(7) "gfedcba"

然后他们问我是否可以在不增加内存使用量的情况下执行此操作(不使用$temp变量或任何变量将反转的字符串复制到)并且我失败了。 这一直困扰着我,从那以后我试图多次解决这个问题,但我经常失败。

我最近的尝试看起来像这样:

$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
    $s = $s{$i * 2} . $s;
}
var_dump($s);
// outputs string(14) "gfedcbaabcdefg"

这不是解决问题的方法&#34; abcdefg&#34;在循环之后,因为那时我仍然会使用的内存量增加一倍。我需要在循环的每次迭代中删除最后一个字符。

我试图像这样使用mb_substr

$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
    $s = $s{$i * 2} . mb_substr($s, $length - $i - 1, 1);
}
var_dump($s);

但它只会给我Uninitialized string offset错误。

这是我再次陷入困境的地方。我尝试使用谷歌搜索,但所有解决方案我直接找到echo字符或使用临时变量。

我也找到了问题PHP String reversal without using extra memory,但没有符合我需要的答案。

22 个答案:

答案 0 :(得分:43)

这是一个有趣的。 这是我刚才提出的:

$s = 'abcdefghijklm';
for($i=strlen($s)-1, $j=0; $j<$i; $i--, $j++) {
    list($s[$j], $s[$i]) = array($s[$i], $s[$j]);
}
echo $s;

list()可用于在一个操作中分配变量列表。所以我正在做的只是交换字符(从第一个和最后一个开始,然后是第二个和第二个,依此类推,直到它到达字符串的中间)

输出为mlkjihgfedcba。 不使用除$s和计数器之外的任何其他变量,所以我希望符合您的标准。

答案 1 :(得分:25)

您可以使用PHP string can be thought of as an array of characters中的事实。

然后基本上你要做的就是用相同距离的中间右侧的字符$i替换字符串中间左侧的每个字符$j

例如,在一个由七个字符组成的字符串中,中间字符位于第3位。位置0(距离3)上的字符需要与位置6(3 + 3)上的字符交换,位置1上的字符(距离2)需要与位置5(3 + 2)等处的字符交换

该算法可以实现如下:

$s = 'abcdefg';

$length = strlen($s); 
for ($i = 0, $j = $length-1; $i < ($length / 2); $i++, $j--) {
    $t = $s[$i];
    $s[$i] = $s[$j];
    $s[$j] = $t;
}

var_dump($s);

答案 2 :(得分:10)

$string = 'abc';

$reverted = implode(array_reverse(str_split($string)));

答案 3 :(得分:7)

试试这个:

$s = 'abcdefg';

for ($i = strlen($s)-1; $i>=0; $i--) {
       $s .= $s[$i];
       $s[$i] = NULL;
 }
var_dump(trim($s));

答案 4 :(得分:7)

您可以使用XOR交换技巧。

function rev($str) {
    $len = strlen($str);

    for($i = 0; $i < floor($len / 2); ++$i) {
        $str[$i] = $str[$i] ^ $str[$len - $i - 1];
        $str[$len - $i - 1] = $str[$i] ^ $str[$len - $i - 1];
        $str[$i] = $str[$i] ^ $str[$len - $i - 1];
    }

    return $str;
}

print rev("example");

答案 5 :(得分:6)

这是PHP7版本:

echo "\u{202E}abcdefg"; // outs: gfedcba

答案 6 :(得分:5)

PHP字符串是kinda-sorta mutable,但由于写入时复制,如果没有复制,就很难就地修改它们。上面的一些解决方案有效,但仅仅因为它们是独立的;一些已经失败,因为他们定义了一个没有pass-by-reference参数的函数。要使代码在更大的程序中实际就地运行,您需要特别注意赋值,函数参数和范围。

示例:

$string1 = 'abc';
$string2 = $string1;
$string1[0] = 'b';
print("$string1, $string2");

> "abc, bbc"

我想如果在初始化变量和修改它之间你只使用了引用赋值(&=)和引用参数(function rev(&$string))(或将字符串赋值给对象属性最初,然后永远不会将其分配给任何其他变量),您可能能够更改字符串的原始值而无需进行任何复制。然而,这有点荒谬,而且我认为提出这个问题的采访者并不知道写时复制。

顺便说一句,这与其他语言的不变性并不完全相同,因为它也适用于数组:

$a = [0, 1, 2];
$b = $a;
$b[0] = 1;
print(implode($a).implode($b));

> "012112"

总而言之,除非您专门使用&=运算符,否则所有类型(除PHP5之外的之外的对象)都将分配写入时复制。赋值不会复制它们,但与大多数其他语言(C,Java,Python ......)不同,它们要么改变原始值(数组),要么根本不允许写访问(字符串),PHP将默默地创建一个在进行任何更改之前复制。

当然,如果您切换到具有更多传统指针的语言并且也切换到字节数组而不是字符串,您可以使用XOR来交换每对字符:

for i = 0 ... string.length / 2:
    string[i] ^= string[string.length-1-i] 
    string[string.length-1-i] ^= string[i]
    string[i] ^= string[string.length-1-i]

答案 7 :(得分:4)

基本上@EricBouwers回答,但你可以删除第二个占位符变量$j

function strrev2($str)
{
    $len = strlen($str);
    for($i=0;$i<$len/2;$i++)
    {
        $tmp = $str[$i];
        $str[$i] = $str[$len-$i-1];
        $str[$len-$i-1] = $tmp;
    }

    return $str;
}

测试输出:

echo strrev2("Hi there!"); // "!ereht iH"
echo PHP_EOL;
echo strrev2("Hello World!"); // "!dlroW olleH"

这将通过列表并中途停止,它在最左边和最右边交换,并向内工作,并在中间停止。如果是奇数,则枢轴数字永远不会与自身交换,如果是偶数,则将中间两个交换并停止。为方便起见,唯一使用的额外内存为$len,交换时使用$tmp

如果您想要一个不会返回该字符串的新副本的功能,但只是编辑旧的副本,您可以使用以下内容:

function strrev3(&$str)
{
    $len = strlen($str);
    for($i=0;$i<$len/2;$i++)
    {
        $tmp = $str[$i];
        $str[$i] = $str[$len-$i-1];
        $str[$len-$i-1] = $tmp;
    }
}

$x = "Test String";
echo $x;           // "Test String"
strrev3($x);
echo PHP_EOL;
echo $x;           // "gnirtS tseT"

使用&$str将直接指针传递给字符串进行编辑。

对于像@treegardens这样的简单实现,你可以重写为:

$s = 'abcdefghijklm';
$len = strlen($s);
for($i=0; $i < $len/2; $i++) {
    list($s[$i], $s[$len-$i-1]) = array($s[$len-$i-1], $s[$i]);
}
echo $s;

它具有类似的逻辑,但我简化了for循环。

答案 8 :(得分:3)

以下是解决问题的代码

 <?php
$s = 'abcdefg';
for ($i = 0, $length = mb_strlen($s); $i < $length; $i++) {
    $s = $s{$i}.mb_substr($s,0,$i).mb_substr($s,$i+1);
}
var_dump($s);
?>

答案 9 :(得分:3)

太简单了

//Reverse a String

$string = 'Basant Kumar';
$length = strlen($string);

for($i=$length-1;$i >=0;$i--){
    echo $string[$i];
}

答案 10 :(得分:3)

您还可以使用递归来反转字符串。像这样的东西:

function reverse($s) {

    if(strlen($s) === 1) return $s;

    return substr($s, strlen($s)-1) . reverse(substr($s , 0, strlen($s)-1));
}

你在这里做的实际上是返回字符串的最后一个字符,然后再次使用包含没有最后一个字符的初始字符串的子字符串调用相同的函数。当你到达字符串只是一个字符的点时,你就结束了递归。

答案 11 :(得分:1)

您可以使用substr作为否定开头。

理论&amp;解释

你可以从1到字符串长度的计数器开始for循环,并使用counter * -1将计数器转换为负值)在迭代内调用substr1的长度。

首次,计数器为1,乘以-1会将其转为-1

因此substr('abcdefg', -1, 1);会让你g 下一次迭代substr('abcdefg', -2, 1);将为您提供f
substr('abcdefg', -3, 1);e给你$str = 'abcdefghijklmnopqrstuvwxyz'; for($i=1; $i <= strlen($str); $i++) { echo substr($str, $i*-1, 1); } 等等...

代码

## the same as: sf <- spectrum((AirPassengers), spans = c(3, 3), plot = FALSE)
sf <- spec.pgram((AirPassengers), spans = c(3, 3), plot = FALSE)
x <- sf$freq
y <- log(sf$spec)
plot(x, y, type="l", col="red" )

行动中:https://eval.in/583208

答案 12 :(得分:0)

使用递归函数反转字符串。

df_m = pd.merge(df1, df2, how='outer', left_on=['Name', 'Date'], right_on=['Name', 'Date'], sort=True)

答案 13 :(得分:0)

这是我解决这个问题的方法。

$in = 'This is a test text';
$out = '';
// find string length
$len = strlen($in);

// loop through it and print  it reverse
for ( $i = $len - 1; $i >=0;$i-- )
{
    $out = $out.$in[$i];
 }

echo $out;

答案 14 :(得分:0)

尝试一下

<?php
$str="abcde";
for($i=strlen($str)-1;$i>=0;$i--){
    echo $str[$i];
}
?>

输出

edcba

答案 15 :(得分:0)

我使用了一些内置函数但没有str_rev函数。

<?php


$text = "red";

$arr = str_split($text);

$rev_text =  array_reverse($arr);

echo join(" ",$rev_text);


?>

答案 16 :(得分:0)

你可以试试这个..

$string = "NASEEM";
$total_word = strlen($string);      
for($i=0; $i<=$total_word; $i++)
{
   echo substr($string,$total_word-$i,1);
}

答案 17 :(得分:0)

   <?php
     $value = 'abcdefg';
     $length_value = strlen($value);
     for($i = $length_value-1; $i >=0 ;$i--){    
       echo $value[$i];
     }
   ?>

答案 18 :(得分:0)

以下解决方案非常简单,但它完成了这项工作:

var_dump($reversedString)

string(7) "saerdnA"然后结果:java -jar myapp.jar

答案 19 :(得分:0)

//Reverse String word by word
$str = "Reverse string word by word";
$i = 0;
while ($d = $str[$i]) {
    if($d == " ") {
        $out = " ".$temp.$out;
        $temp = "";
    }
    else
        $temp .= $d;

    $i++;
}
echo $temp.$out;

答案 20 :(得分:0)

public function checkString($str){
    if(!empty($str)){ 
        $i = 0;
        $str_reverse = '';

        while(isset($str[$i])){ 
            $strArr[] = $str[$i];
            $i++;
        }
        for($j = count($strArr); $j>= 0; $j--){ 
            if(isset($strArr[$j])){
                $str_reverse .= $strArr[$j];
            }
        }
        if($str == $str_reverse){ 
            echo 'It is a correct string';
        }else{
            echo 'Invalid string';
        }
    }
    else{
        echo 'string not found.';
    }
}

答案 21 :(得分:-1)

试试这个

$warn = 'this is a test'; 
$i=0;
while(@$warn[$i]){
  $i++;} 
while($i>0) 
{ 
  echo $warn[$i-1]; $i--;
}