关于循环的高级应用
提示:这里可以添加系列文章的所有文章的目录,目录需要自己手动添加
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
1.嵌套循环之行和列(先后)
从二个角度理解循环:
1.最内层的循环通常是执行实际工作的循环,而外层循环则用于控制迭代的范围和顺序。
2.执行的先后顺序,根据先后理解
#include <stdio.h>
int main()
{
int i, j,rows = 5; // rows变量可以设置你想要的三角形的高度
for (i = 1; i <= rows; i++)
{ // 外层循环控制行数
for (j = 1; j <=i ; j++)//内层循环控制每一行类数
{ // 打印空格
printf("*");
}
printf("\n"); // 每打印完一行后换行
}
return 0;
}
结果:
*
**
***
****
*****
其实在我看来没有行和列之分,只有执行先后顺序之分。打印是一行一行打印的,
先打印一个*,
for (i = 1; i <= rows; i++)
{ // 外层循环控制行数
for (j = 1; j <=i ; j++)//内层循环控制每一行类数
{ // 打印空格
printf("*");
>>>>>>>先打印,由于打印是一行一行打印的,
>>>>>>>则内循环这里是控制每一个行的具体情况
}
printf("\n"); // 每打印完一行后换行
}
也可以这样想:
要打印*和** *** *****
for (j = 1; j <=n ; j++)
{
printf("*");
}
当n=1时,打印*,
n=2时,打印**,
这么实现n持续增长呢?
在外面在嵌套一个n
for (i = 1; i <= n; i++)
{ // 外层循环控制行数
for (j = 1; j <=n ; j++)//内层循环控制每一行类数
{ // 打印空格
printf("*");
>>>>>>>先打印,由于打印是一行一行打印的,
>>>>>>>则内循环这里是控制每一个行的具体情况
}
printf("\n"); // 每打印完一行后换行
}
2.内外循环之条件检测频率
通过检测频率和更改变量的角度来判断是否增加限制条件
反转字符串 s 中的所有字母,而非字母字符保持原位置。
class Solution{
public:
string reverseOnlyLetter(string s)
{
int bgain = 0;
int end = s.size()-1;
while(bgin<end)
{
while(!IsChar(s[begin]) && begain<end)//不是字符,bgin一直++
{
begin++;//
}
<<<<<<<<<<<<<<<<<<<<<<疑问?<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
为什么外循环已经限制了bgin<end,内循环还需要限制begain<end,why?
1.刚进入外循环是满足条件bgin<end,但是进入内循环中,由于内循环改变了begin,导致内循环不一定满足条件begain<end。
说明:循环条件是是一种入口条件,只要能进入一次,就会执行完循环体中代码一次。
当不满足条件时,并不会马上跳出循环,而是继续执行完本次循环,下一次进入循环体,会因为不满足条件而停止循环。
则:
单一循环体,每一次循环结束后,在进入循环体前都会检测条件, 及时检测循环体条件
嵌套循环,内循环每一次循环结束后,会进入在进入循环体前都会检测内循环条件,只有当内循环执行完,才会跳出内循环进入外循环,也就是
**外循环检测频率是1 内循环(执行完毕了)已经检测n次了。**
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
while(!IsChar(s[end]) && begain<end)
{
end--;
}
swap(s[begin],s[end]);
begain++;
end--;
}
}
也就是说外循环不一定可以限制内循环中的变量,只能说外循环可以限制进入内循环的起点,至于在内循环中做何改变,以及内循环的结束条件它无法控制。
循环条件是是一种入口条件,当满足条件就会进入循环体内部,进入之后有何造化我不管。也就是说它控制能进入的起点。它也是一种出口条件,当不满足条件,就有跳出循环体。
外循环检测频率一次 而 内循环(执行完毕了)已经检测n次了。
class Solution{
public:
string reverseOnlyLetter(string s)
{
int bgain = 0;
int end = s.size()-1;
while(bgin<end)
{
//为什么这样,if就不用加入限制条件呢?
//因为此处的跳出循环采用的是continue,也就是和跳出循环while(bgin<end),
if(!IsChar(s[begin]))//不是字符,bgin一直++
{
begin++;
continue;
}
if(!IsChar(s[end]))
{
end--;
continue;
}
swap(s[begin],s[end]);
begain++;
end--;
}
}
3关于循环的理解
1.等待循环条件为假,跳出循环
说明出循环时,条件为假;
int a=0;
while(a!=5) //等待a=5,当a=5时才能跳出循环
{
printf("%d",a);//1,2,3,4,5
a++;
}
printf("%d",a);//5
4.if retrun 卫语句的应用:也叫排除法,提前返回大法。
例如一个合法的信息:要求 0<=age<=120,name不能为空,height在50<=x<=250。
bool isValidinfo(int age, const string& name) {
if (age >=0 && age <= 120) //条件1
{
if (!name.empty())
{
if(height>=50 && height<=250 )
{
retrun true;
}
else
printf("非法身高");
retrun false;
}
else
printf("非法名字");
retrun false;
}
else
printf("非法年龄");
retrun false;
}
嵌套的判断很麻烦,而且条件和return不同步,阅读麻烦。
可以用卫语句,if retrurn 它用于在满足特定条件时立即退出函数,并返回一个值。这种模式可以减少嵌套的深度,使代码更加简洁和清晰。
1.能进入后面的某行代码,说明该代码前面所有的条件全部不满足。从而实现嵌套逻辑,就是逻辑递进关系
bool isValidinfo(int age, const string& name) {
if (age < 0 || age > 120) //条件1
{
printf("非法年龄");
return false; // 不合法的年龄,提前退出
}
//能执行到这里,说明条件1不满足
if (name.empty()) //条件2
{
printf("非法名字");
return false; // 名字不能为空
}
能执行到这里,说明条件1和条件2都不满足
if(height<50 ||height>250 ) //条件3
{
printf("非法身高");
return false;
}
//能执行到这里,说明条件1、条件2和条件3都不满足
return true; // 合法的年龄和名字
}
4.while if(条件) continue/break 的提前返回大法
和if return有异曲同工之处。
class Solution{
public:
string reverseOnlyLetter(string s)
{
int bgain = 0;
int end = s.size()-1;
while(bgin<end)
{
//为什么这样,if就不用加入限制条件呢?
//因为此处的跳出循环采用的是continue,也就是和跳出循环while(bgin<end),
if(!IsChar(s[begin]))//条件1
{
begin++;
//条件1满足,就begin++,提前返回到while(bgin<end),执行下一次循环
continue;
}
//能执行到这里,说明条件1不满足,就是说s[begin]是字符串
if(!IsChar(s[end]))
{
end--;
continue;
}
//能执行到这里,说明条件1和条件2都不满足,就是说s[begin]和s[end]都是是字符串
swap(s[begin],s[end]);
begain++;
end--;
}
}