一.递归实现回文字符串判断
#include<bits/stdc++.h>
using namespace std;
bool ispalindrome(string s, int i, int j) {
if (i >= j) return true;//判断结束
if (s[i] == s[j]) return ispalindrome(s, i+1, j-1);//不断向中间逼近判断
else return false;
}
int main(){
string s;
cin >>s ;
if(ispalindrome(s,s[0],s[s.size()])) cout << "Yes";
else cout << "No";
}
二.用递归法倒叙输出一个正整数
#include<bits/stdc++.h>
using namespace std;
void cal(int n){
cout << n % 10;//输出末位
if(n / 10) cal(n / 10);//判断是否为最高位,否则一直倒序递归
}
int main(){
int n;
cin >> n;
cal(n);
return 0;
}
三.n个自然数中取r个数的组合
1.问题思路描述:
分析图片中的数据,得到的组合数的规律为:
(1)固定5,其后就是求解n = 4,r = 2的组合数,共6个组合
(2)固定4,其后就是求解n = 3,r = 2的组合数,共3个组合
(3)固定3,其后就是求解n = 2,r = 2的组合数,共1个组合
这就找到了“5个数中的3个数的组合”与“4个数中的2个数的组合、3个数中的2个数的组合、2个数中的2个数的组合”的递归关系。
经数学归纳法,得出以下结论:
(1)n个数中r个数组合递推到“n - 1个数中r - 1个数有组合,n - 2个数中r - 1个数有组合,n - 3个数中r - 1个数有组合……r - 1个数中r - 1个数有组合”,共n - r + 1次递归。
(2)递归停止的条件为r = 1。(因为r - 1 = 0没有数了)
2.可执行的源代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e2 + 10;
int a[N];
void cal(int n,int r){
for(int i = n;i >= r;i -- ){//最后位置的数取值为 r =< i <= n
a[r] = i;
if(r > 1) cal(i - 1,r - 1);//r > 1继续执行,此时前面还有位置,需要向前递归;r在每个位置向前递归时取值范围不同,目的是保证前面的数严格小于后面的数且每个位置均有数字。
else {//r == 1就输出结果(此时后面的位置已经确定,r == 1时即产生一个全排列。),注意r == 1时for循环仍然执行,i仍会减小从而继续打印。
for(int j = a[0];j > 0;j -- )
cout << a[j];
puts("");
}
}
}
int main(){
int n,r;
cin >> n >> r;
a[0] = r;//巧妙之处:充当全局变量,记录r(即是几排列)
cal(n ,r);
return 0;
}
3.运行界面截图
4.反思:
为什么设计后每个组合数中的数据从大到小排列?
因为递归算法设计是要找出大规模的问题与小规模的问题之间的关系。
四.输出一个集合的全部子集
1.问题思路描述:
0表示不在子集中不输出,1表示在子集中可以输出。当所有字符的状态确定时输出子集。然后返回上一次不确定的字符改变它的状态,并让不确定的字符减一直至不确定的字符为0 。
即这是一种排列组合的问题,将每个元素存在与否用0,1来表示,那么就是一个0,1的排列组合,并将其放在一个数组中,通过递归可以加以实现。
引入回溯法:
2.可执行的源代码:
#include <bits/stdc++.h>
using namespace std;
template <class T> //应用模板类使得应用更广泛。
void cal(T b[], int t[], int index, int len) {
if (index == len) {//终止条件:最后一位状态确定(前面的数位状态当然也已经确定)
for (int i = 0; i < len; i++){
if (t[i] == 1)//1表示在子集中可以输出
cout << b[i];
}
puts("");
}
else{
t[index] = 0;
cal(b, t, index + 1, len);
t[index] = 1;//执行完0接着执行1,遍历所有情况
cal(b, t, index + 1, len);//此步之后就回溯
/*for(int i = 0;i <= 1;i ++ ){
t[index] = i;
cal(b,t,index + 1,len);
}
*/
}
}
int main() {
int n;
cin >> n;
char b[n + 1];
for(int i = 0;i < n;i ++ ) cin >> b[i];
int t[n + 1];//状态数组,储存0和1
cal(b, t, 0, n);
return 0;
}
3.运行界面截图
五.整数因子分解
1.问题思路描述:
由上图分析,整数因子最终均能分解为1,则将1作为递归的最终条件。
2.可执行的源代码:
#include<bits/stdc++.h>
using namespace std;
int ans = 0;
void cal(int n){
if(n == 1) ans ++ ;//终结条件
else{
for(int i = 2;i <= n;i ++ ){
if(n % i == 0) cal(n/i);
}
}
}
int main(){
int n;
cin >> n;
cal(n);
cout << ans;
return 0;
}