Обратная строка без strrev

Некоторое время назад во время собеседования я получил задачу изменить строку на 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" 

то они спросили меня, могу ли я сделать это без удвоения использования памяти (не используя переменную $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" 

Это не решение отбросить «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); 

но это только дает мне Uninitialized string offset ошибки Uninitialized string offset .

Вот где я застрял (снова). Я попытался выполнить поиск в Google, но все решения, которые я нашел, либо echo -символы, либо использовать временную переменную.

Я также нашел обратную задачу PHP PHP, не используя дополнительную память, но нет ответа, который бы соответствовал моим потребностям.

Это интересно. Вот что я только что придумал:

 $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 и счетчиков, поэтому я надеюсь, что это соответствует вашим критериям.

Вы можете использовать тот факт, что в 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); 
 $string = 'abc'; $reverted = implode(array_reverse(str_split($string))); 

Вы можете использовать трюк обмена 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"); 

Попробуй это:

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

Строки PHP являются своего рода изменчивыми , но из-за копирования на запись очень сложно изменить их на месте без создания копии . Некоторые из вышеперечисленных решений работают, но только потому, что они автономны; некоторые из них уже сбой, потому что они определяют функцию без аргумента 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] 

Вот это версия PHP7:

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

В основном @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-loop совсем немного.

Вот мой код для решения вашей проблемы

  <?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); ?> 

Слишком просто

 //Reverse a String $string = 'Basant Kumar'; $length = strlen($string); for($i=$length-1;$i >=0;$i--){ echo $string[$i]; } 

Вы также можете использовать рекурсию для изменения строки. Что-то вроде этого, например:

 function reverse($s) { if(strlen($s) === 1) return $s; return substr($s, strlen($s)-1) . reverse(substr($s , 0, strlen($s)-1)); } 

То, что вы здесь делаете, фактически возвращает последний символ строки, а затем снова вызывает ту же функцию с подстрокой, которая содержит начальную строку без последнего символа. Когда вы достигнете точки, когда ваша строка – всего один символ, вы заканчиваете рекурсию.

Вы можете использовать этот код для изменения строки без использования зарезервированной функции в php.

Код:

 <?php function str_rev($y)// function for reversing a string by passing parameters { for ($x = strlen($y)-1; $x>=0; $x--) { $y .= $y[$x]; $y[$x] = NULL; } echo $y; } str_rev("I am a student"); ?> 

Вывод:

 tneduts a ma I 

В приведенном выше коде мы передали значение строки в качестве параметра. Мы выполнили инверсию строки, используя для цикла.

вы можете использовать substr с отрицательным началом.

Теория и пояснения

вы можете начать с цикла loop с счетчиком от 1 до длины строки и вызвать substr внутри итерации с помощью counter * -1 ( который преобразует счетчик в отрицательное значение ) и длиной 1 .

Таким образом, первый счетчик будет равен 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); } 

В действии: https://eval.in/583208

 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.'; } } в 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.'; } } 
 //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; 

Следующее решение очень простое, но оно делает работу:

 $string = 'Andreas'; $reversedString = ''; for($i = mb_strlen($string) - 1; $i >= 0; $i--){ $reversedString .= $string[$i]; } 

var_dump($reversedString) то результаты: string(7) "saerdnA"

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

вы можете попробовать это ..

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

Я использовал некоторую встроенную функцию, но без функции str_rev.

 <?php $text = "red"; $arr = str_split($text); $rev_text = array_reverse($arr); echo join(" ",$rev_text); ?> 

Попробуй это

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