前一段时间在求职面试中,我得到了在不使用PHP的情况下在PHP中反转字符串的任务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"
Run Code Online (Sandbox Code Playgroud)
然后他们问我是否可以在不增加内存使用量的情况下这样做(不使用$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"
Run Code Online (Sandbox Code Playgroud)
它不是在循环之后切断"abcdefg"的解决方案,因为那时我仍然会使用的内存量增加一倍.我需要在循环的每次迭代中删除最后一个字符.
我试着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);
Run Code Online (Sandbox Code Playgroud)
但它只给我Uninitialized string offset
错误.
这是我被困(再次)的地方.我尝试使用谷歌搜索,但所有解决方案我echo
直接找到字符或使用临时变量.
我还发现问题PHP字符串逆转而不使用额外的内存,但没有符合我需要的答案.
ksb*_*sbg 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;
Run Code Online (Sandbox Code Playgroud)
list()
可用于在一个操作中分配变量列表.所以我正在做的只是交换字符(从第一个和最后一个开始,然后是第二个和第二个,依此类推,直到它到达字符串的中间)
输出是mlkjihgfedcba
.不使用任何其他变量$s
和计数器,所以我希望符合您的标准.
ebo*_*ebo 25
您可以使用以下事实:在PHP中,字符串可以被视为一个字符数组.
那么基本上你要做的就是用相同距离的中间右边$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);
Run Code Online (Sandbox Code Playgroud)
Bar*_*ach 10
$string = 'abc';
$reverted = implode(array_reverse(str_split($string)));
Run Code Online (Sandbox Code Playgroud)
试试这个:
$s = 'abcdefg';
for ($i = strlen($s)-1; $i>=0; $i--) {
$s .= $s[$i];
$s[$i] = NULL;
}
var_dump(trim($s));
Run Code Online (Sandbox Code Playgroud)
你可以使用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");
Run Code Online (Sandbox Code Playgroud)
PHP字符串有点可变,但由于写入时复制,很难在没有复制的情况下就地修改它们.上面的一些解决方案有效,但仅仅因为它们是独立的; 一些已经失败,因为他们定义了一个没有pass-by-reference参数的函数.要使代码在更大的程序中实际就地运行,您需要特别注意赋值,函数参数和范围.
例:
$string1 = 'abc';
$string2 = $string1;
$string1[0] = 'b';
print("$string1, $string2");
> "abc, bbc"
Run Code Online (Sandbox Code Playgroud)
我想如果在初始化变量和修改它之间你只使用了引用赋值(&=
)和引用参数(function rev(&$string)
)(或者最初将字符串赋值给一个对象属性,然后再将其分配给任何其他变量),你可能会能够在不进行任何复制的情况下更改字符串的原始值.然而,这有点荒谬,而且我认为提出这个问题的采访者并不知道写时复制.
顺便说一句,这与其他语言的不变性并不完全相同,因为它也适用于数组:
$a = [0, 1, 2];
$b = $a;
$b[0] = 1;
print(implode($a).implode($b));
> "012112"
Run Code Online (Sandbox Code Playgroud)
总而言之,除非您专门使用运算符,否则所有类型(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]
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
37072 次 |
最近记录: |