[英]Write a recursive function that reverses the input string
我一直在閱讀 C++ For Everyone 一書,其中一個練習說要編寫一個函數string reverse(string str)
,其中返回值是str
的反向。
有人可以寫一些基本的代碼並向我解釋嗎? 我從昨天開始就一直盯着這個問題,想不通。 我得到的最遠的是讓函數返回str
的第一個字母(我仍然不知道它是怎么發生的)
這是我得到的(發布這個問題一個小時后):
string reverse(string str)
{
string word = "";
if (str.length() <= 1)
{
return str;
}
else
{
string str_copy = str;
int n = str_copy.length() - 1;
string last_letter = str_copy.substr(n, 1);
str_copy = str_copy.substr(0, n);
word += reverse(str_copy);
return str_copy;
}
return word;
}
如果我輸入“Wolf”,它會返回 Wol。 有人幫我在這里如果我return word
而不是return str_copy
那么我得到一個w
如果我return last_letter
那么我得到一個l
相反,我將解釋遞歸算法本身。 以應該產生“tupni”的“輸入”為例。 您可以通過遞歸反轉字符串
試試這個
string reverse(string &s)
{
if( s.length() == 0 ) // end condtion to stop recursion
return "";
string last(1,s[s.length()-1]); // create string with last character
string reversed = reverse(s.substr(0,s.length()-1));
return last+reversed; // Make he last character first
}
遞歸函數必須具有以下屬性
這個遞歸函數基本上創建了一個包含最后一個字符的字符串,然后用字符串的其余部分(不包括最后一個字符)再次調用自己。 真正的切換發生在返回 last+reversed 的最后一行。 如果情況相反,則什么都不會發生。
這是非常低效的,但它可以展示這個概念。
只是建議一種更好的處理遞歸的方法:
在 C++ 中使用遞歸進行字符串反轉:
#include <iostream>
#include <string>
using namespace std;
string reverseStringRecursively(string str){
if (str.length() == 1) {
return str;
}else{
return reverseStringRecursively(str.substr(1,str.length())) + str.at(0);
}
}
int main()
{
string str;
cout<<"Enter the string to reverse : ";
cin>>str;
cout<<"The reversed string is : "<<reverseStringRecursively(str);
return 0;
}
這是我的遞歸函數版本,用於反轉輸入字符串:
void reverse(char *s, size_t len)
{
if ( len <= 1 || !s )
{
return;
}
std::swap(s[0], s[len-1]);// swap first and last simbols
s++; // move pointer to the following char
reverse(s, len-2); // shorten len of string
}
我不會為你寫一個完整的算法,但這里有一個提示:
如何交換最外面的兩個字符,然后將相同的應用於中間的字符?
哦,如果那本書真的提出了string reverse(string str)
作為合適的函數簽名,那就扔掉它,買一本好書吧。
最短和最簡單
class Solution {
public:
string reverseString(string s) {
string str;
if(s != "\0"){
str = reverseString(s.substr(1, s.length()));
str += s.substr(0,1);
}
return str;
}
};
我知道我不應該給出解決方案,但既然沒有人提到這個簡單的解決方案,我想我應該分享它。 我認為代碼字面上就是算法,所以不需要偽代碼。
void c_plusplus_recursive_swap_reverse(std::string::iterator start,
std::string::iterator end)
{
if(start >= end) {
return;
}
std::iter_swap(start, end);
c_plusplus_recursive_swap_reverse(++start, --end);
}
調用它使用:
c_plusplus_recursive_swap_reverse(temp.begin(), temp.end());
1 行遞歸解決方案:
string RecursiveReverse(string str, string prev = "") {
return (str.length() == 0 ? prev : RecursiveReverse(str.substr(0, str.length()-1), prev += str[str.length()-1]));
}
你這樣稱呼它:
cout << RecursiveReverse("String to Reverse");
所有現有的解決方案都有太多的代碼沒有真正做任何事情,所以,這是我的看法:
#include <iostream>
#include <string>
std::string
r(std::string s)
{
if (s.empty())
return s;
return r(s.substr(1)) + s[0];
}
int
main()
{
std::cout << r("testing") << std::endl;
}
PS 我偶然發現了這個問題,試圖為 C 中的char *
s+1
std::string
找到一種 C++ 方式; 沒有走s.substr(1, s.length()-1)
的整個路線,這看起來太難看了。 原來,有std::string::npos
,這意味着直到字符串的末尾,它已經是第二個參數的默認值,所以, s.substr(1)
就足夠了(另外,它看起來也更有效率並與 C 中的簡單s + 1
相當)。
但是請注意,遞歸通常不會隨着輸入變大而擴展,除非編譯器能夠執行所謂的尾遞歸優化。 (命令式語言很少依賴遞歸。)
但是,為了使尾遞歸優化被激活,一般要求,(0),遞歸只發生在return
語句中,並且,(1),遞歸的結果不執行進一步的操作在父函數中回調。
例如,在上述情況下, + s[0]
在子調用完成后由父級邏輯完成(即使您使用更丑陋的s[s.length()-1] +
路由也可能如此),因此,它也可能阻止大多數編譯器進行尾遞歸優化,從而使該函數在大輸入上非常低效(如果不是由於堆耗盡而完全損壞)。
(對於它的價值,我已經嘗試編寫一個對尾遞歸更友好的解決方案(確保通過函數本身的參數來增加返回結果),但是對生成的二進制文件的反匯編似乎表明它比在像 C++ 這樣的命令式語言中,請參閱gcc:如果我在 C++ 中返回 std::string,是否沒有尾遞歸? 。)
您可以實現類似於 std::reverse 的自己的反向。
template <typename BidirIt>
void reverse(BidirIt first, BidirIt last)
{
if((first == last) || (first == --last))
return;
std::iter_swap(first, last);
reverse(++first, last);
}
我做了這樣的事情,它在原地進行了逆轉。 我取了兩個變量,它們從字符串的兩端到字符串的中心遍歷字符串,當它們相互重疊或相等時,反轉終止。
舉個例子:輸入string str = "abcd"
並調用函數為
ReverseString(str,0,str.length()-1);
並遞歸地遞增/遞減變量指針。 首先指針指向'a'
和'd'
並交換它們,然后它們指向'b'
和'c'
並交換它們。 最終i >= j
要求基本情況為真,因此遞歸終止。 這個問題的主要內容是將輸入字符串作為參考傳遞。
string ReverseString(string& str,int i,int j){
if(str.length() < 1 || str == "" || i >= j){
return "";
}
else{
char temp = str[i];
str[i] = str[j];
str[j] = temp;
ReverseString(str,i+1,j-1);
}
return str;
}
字符串可以就地反轉。 如果我們從盡可能小的字符串開始,即一個字符串,我們不需要做任何事情。 這是我們停止或從遞歸調用返回的地方,它成為我們的基本情況。
接下來,我們必須考慮交換最小字符串的通用方法,即兩個或更多字符。 最簡單的邏輯是將當前字符str[current_index]
與對面的字符str[str_length-1 - current_index]
。
最后,再次為下一個索引調用反向函數。
#include <iostream>
using namespace std;
void reverse_string(std::string& str, int index, int length) {
// Base case: if its a single element, no need to swap
// stop swapping as soon as we reach the mid, hence index*2
// otherwise we will reverse the already reversed string
if( (length - index*2) <= 1 ) {
return;
}
// Reverse logic and recursion:
// swap current and opposite index
std::swap(str[index], str[length-1 - index]);
// do the same for next character (index+1)
reverse_string(str, index+1, length);
}
int main() {
std::string s = "World";
reverse_string(s, 0, s.length());
std::cout << s << endl;
}
已經有一些很好的答案,但我想用完整的遞歸反向字符串添加我的方法。
#include <iostream>
#include <string>
using namespace std;
char * reverse_s(char *, char*, int,int);
int main(int argc, char** argv) {
if(argc != 2) {
cout << "\n ERROR! Input String";
cout << "\n\t " << argv[0] << "STRING" << endl;
return 1;
}
char* str = new char[strlen(argv[1])+1];
strcpy(str,argv[1]);
char* rev_str = new char[strlen(str)+1];
cout<<"\n\nFinal Reverse of '" << str << "' is --> "<< reverse_s(str, rev_str, 0, strlen(str)) << endl;
cin.ignore();
delete rev_str, str;
return 0;
}
char* reverse_s(char* str, char* rev_str, int str_index, int rev_index ) {
if(strlen(str) == 1)
return str;
if(str[str_index] == '\0' ) {
rev_str[str_index] = '\0';
return rev_str;
}
str_index += 1;
rev_index -=1;
rev_str = reverse_s(str, rev_str, str_index, rev_index);
if(rev_index >= 0) {
cout << "\n Now the str value is " << str[str_index-1] << " -- Index " << str_in
dex << " Rev Index: " << rev_index;
rev_str[rev_index] = str[str_index-1];
cout << "\nReversed Value: " << rev_str << endl;
}
return rev_str;
}
void reverse(string &s, int &m) {
if (m == s.size()-1)
return;
int going_to = s.size() - 1 - m;
string leader = s.substr(1,going_to);
string rest = s.substr(going_to+1,s.size());
s = leader + s.substr(0,1) + rest;
reverse(s,++m);
}
int main ()
{
string y = "oprah";
int sz = 0;
reverse(y,sz);
cout << y << endl;
return 0;
}
這是我的 3 行字符串反轉
std::string stringRevers(std::string s)
{
if(s.length()<=1)return s;
string word=s.at(s.length()-1)+stringRevers(s.substr(0,s.length()-1));//copy the last one at the beginning and do the same with the rest
return word;
}
void ClassName::strgRevese(char *str)
{
if (*str=='\0')
return;
else
strgRevese(str+1);
cout <<*str;
}
問題是寫一個遞歸函數。 這是一種方法。 不是一個整潔的代碼,但做了什么需要。
/* string reversal through recursion */
#include <stdio.h>
#include <string.h>
#define size 1000
char rev(char []);
char new_line[size];
int j = 0;
int i =0;
int main ()
{
char string[]="Game On";
rev(string);
printf("Reversed rev string is %s\n",new_line);
return 0;
}
char rev(char line[])
{
while(line[i]!='\0')
{
i++;
rev(line);
i--;
new_line[j] = line[i];
j++;
return line[i];
}
return line[i];
}
它將遞歸地反轉原始字符串
void swap(string &str1, string &str2)
{
string temp = str1;
str1 = str2;
str2 = str1;
}
void ReverseOriginalString(string &str, int p, int sizeOfStr)
{
static int i = 0;
if (p == sizeOfStr)
return;
ReverseOriginalString(str, s + 1, sizeOfStr);
if (i <= p)
swap(&str[i++], &str[p])
}
int main()
{
string st = "Rizwan Haider";
ReverseOriginalString(st, 0, st.length());
std::cout << "Original String is Reversed: " << st << std::endl;
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.