我一直在学习递归,我确实得到了关于它们如何工作以及如何编码它们的概念。现在,正常的递归很容易可视化,但是当递归涉及循环时,它们完全令人费解。
让我们首先回答这个问题,假设,我有一个字符串,我必须找到可以使用该字符串生成的有效IP地址。
实施例
11211
可能的IP地址
1.1.2.11
1.1.21.1
1.12.1.1
11.2.1.1
我试图用给定代码
之类的东西来实现这一点vector<string> v;
string period(string str,int i){
size_t pos=str.find_last_of(".");
if(pos==string::npos)
str.insert(i+1,".");
else
str.insert(pos+2,".");
v.push_back(str);
return str;
}
void recursion(string str){
for(int i=0;i<=2;i++)
{
cout<<i<<'\n';
string strx=period(str,i);
if(count(strx.begin(),strx.end(),'.')<4)
recursion(str);
}
}
bool validIPaddress(string str){
//return true for valid ip address
}
int main () {
string str("11211");
recursion(str);
for(vector<string>::iterator it=v.begin();it!=v.end();++it){
if(validIPaddress(*it))
cout<<*it<<'\n';
}
}
我已经为我的逻辑制作了一张照片。
尝试我可以将.
置于字符串之间的每个可能的位置,并将每个可能的组合保留在已全局声明的向量中,并且不要在字符串中放置超过3个句点。< / p>
递归完成后,我使用句点进行所有可能的组合,我可以循环遍历该向量并找到有效的。
现在,问题在于,当我尝试实现这个逻辑时,我的输出并不像我预期的那样。我试着调试我的代码并看一眼我做错了但是我无处可去
如何使用递归实现上述问题的解决方案?
此致
BOTJr。
答案 0 :(得分:2)
你的想法很完美,你不应该使用循环。通常我们在处理递归函数时不使用循环。实际上,这个问题不涉及循环,你只需要两次调用递归函数。
你的问题是每个循环都会再次调用你的函数,这意味着再多三次迭代。每次迭代将再次意味着三次迭代,这将被无限调用。此外,您保存向量中的每个字符串,但它足以保存正确的字符串。由于我们需要知道下一个句点的位置,我们将在递归函数中添加一个新的位置参数。
首先,我们必须将期间添加到预期的位置。
void recursion(const string& str, const size_t i = 1){
//Create a copy of the constant string
string strx = str;
//The insert method will insert one dot before the
//i positioned character in the string
strx.insert(i, 1, '.');
//...
在插入这一段时间之后,我们只需要回忆一下这个功能,但是只有在有新时期的地方,或者我们没有3个需要的时期。
//...
if(count(strx.begin(), strx.end(), '.') < 3)
{
//If the count of periods in the new string is under three,
//then we need to add a new period.
if (i < strx.size() - 2) recursion(strx, i + 2);
}
else
{
//The else means, the number of periods if greater or equal
//to 3. Actually, the only possibility is the equality, so
//we can add the string to the vector
v.push_back(strx);
}
//Also, we call the recursion on the unmodified string, which means
//we will get IP numbers starting with two numbers too.
if (i < str.size() - 1) recursion(str, i + 1); //recall on original
}
这样,您不必在最后调用检查功能。请注意,我们会在第一次调用时检查长度(或大小) - 2,因为我们不希望获得1..12.11
。
答案 1 :(得分:1)
我根据我的问题做了一些改变。我使用了地图,但也可以使用矢量。
此外,ValidIPaddress函数考虑对IP地址的基本检查,但是它不会检查诸如位于0-255
范围内的八进制的检查。
map<string,string> v;
bool validIPaddress(string);
string period(string str,int i){
size_t pos=str.find_last_of(".");
if(pos==string::npos)
str.insert(i+1,".");
else
if(pos+i+2<=str.length())
str.insert(pos+i+2,".");
else return "terminate";
if(validIPaddress(str))
v[str]=str;
return str;
}
void recursion(string str){
if(str!="terminate")
{
if(count(str.begin(),str.end(),'.')<3)
{
string other=str;
for(int i=0;i<=2;i++)
{
recursion(period(str,i));
str=other;
}
}
}
}
bool validIPaddress(string str){
int periods_used=count(str.begin(),str.end(),'.');
if(periods_used!=3)
return false;
size_t pos=str.find_last_of('.');
if(str.substr(pos+1).length()<1)
return false;
int i=0;
while(i<3)
{
int found=str.find('.');
string strx=str.substr(0,found);
if(strx.length()<1 || strx.length()>3)
return false;
str=str.substr(found+1);
i++;
}
return true;
}
int main () {
string str("11211");
if(str.length()>=4)
recursion(str);
else
{
cout<<"No possible IP addresses can be generated."<<'\n';
exit(1);
}
for(map<string,string>::iterator it=v.begin();it!=v.end();++it)
cout<<it->first<<'\n';
}
输出:
1.1.2.11
1.1.21.1
1.12.1.1
11.2.1.1