目录
*递归的思想
(1)找重复 例如我要写n的阶乘,n的阶乘可以表示n*(n-1)的阶乘,求n-1的阶乘是原问题的重复(规模更小)--子问题
i)找到一种划分方式 ii)找到一种递推公式
(2)找变化 变化的量应该作为边界(3)找边界 出口 一般我们用if条件来规定出口
我们可以将递归分解为:(1)直接量+小规模问题
(2)多个小规模问题
典型例题
斐波那契数列
啥叫斐波那契数列呢?
如1,1,2,3,5,8,13,21.....就是除了第一个和第二个数之外,其他数等于前两个数之和
#include<iostream>
#include<string>
using namespace std;
//斐波那契数列的指定的前n项
int Fib(int n)
{
if (n == 1 || n == 2)
{
return 1;
}
return Fib(n - 2) + Fib(n - 1);
}
int main()
{
int n;
cin >> n;
int N = Fib(n);
cout << N;
return 0;
}
递归求最大公约数
思路:我们先让n%m,如果能余数为0,那么m就是最大公约数,如果余数不是0,那我们把余数叫做k,那就m%k,如果能余数是0,那k就是最大公约数,不是0,那就让k%(m与k的余数),一直这样操作,总会找到一个数,哪怕是1
#include<iostream>
#include<string>
using namespace std;
int MAx(int n, int m)
{
if (n % m ==0)
{
return m;
}
else {
MAx(m, n % m);
}
}
int main()
{
//n,m的最大公约数
int n, m;
cin >> n >> m;
int number = MAx(n, m);
cout << number<<endl;
return 0;
}
汉诺塔
相传在古印度圣庙中,有一种被称为汉诺塔(Hanoi)的游戏。该游戏是在一块铜板装置上,有三根杆(编号A、B、C),在A杆自下而上、由大到小按顺序放置若干个金盘(如下图)。游戏的目标:把A杆上的金盘全部移到C杆上,并仍保持原有顺序叠好。操作规则:每次只能移动一个盘子,并且在移动过程中三根杆上都始终保持大盘在下,小盘在上,操作过程中盘子可以置于A、B、C任一杆上
我们的思路就是我们先把上面N-1个盘子,放到中间的withPole(我们也叫做help),就是下面这个图
然后我们把最下面那个盘子放到toPole上
最后把withPole上的盘子放到toPole上
我们用代码写这个过程的时候,我注意,我们不是直接挪动,而是借助另一个help来移动
我们先把上面N-1个盘子,放到中间的withPole(我们也叫做help),是借助了toPole移过去的
最后把withPole上的盘子放到toPole上是借助from移过去的
所以下面用代码实现的时候要加一个help辅助
#include<iostream>
#include<string>
using namespace std;
void HanoiTower(int N, string from, string to, string help)
{
if (N == 1)
{
cout << " move " << N << " from " << from << " to " << to << endl;
}
else {
HanoiTower(N - 1, from, help, to);
cout<< " move " << N << " from " << from << " to " << to << endl;
HanoiTower(N - 1, help, to, from);
}
}
int main()
{
HanoiTower(3, "A", "C", "B");
return 0;
}
二分查找法的递归形式
#include<iostream>
#include<string>
using namespace std;
int binarySearch(int arr[], int begin, int end, int key)
{
if (begin > end)
return -1;
int mid = (begin + end) / 2;
int midVal = arr[mid];
if (midVal < key)
{
return binarySearch(arr, mid + 1, end, key);
}
else if (midVal > key)
{
return binarySearch(arr, begin, mid - 1, key);
}
else {
return mid;
}
}
int main()
{
int arr[] = { 0,1,2,3,4,5,6,7,8,9 };
int index = binarySearch(arr, 0, 9, 5);
cout << index << endl;
return 0;
}
小白上楼梯问题
小白正在上楼梯,楼梯有n阶台阶,小白一次一次可以上1阶,2阶或3阶,实现一个方法,计算小白有多少种走完楼梯的方式。
思路:我们可以先倒着想这个问题,我们可以从n-1阶直接走到n阶,也可以从n-2阶走到n阶,也可以从n-3阶走到n阶,这样想的前提是小白已经到达了n-1或n-2或者n-3阶
n-1阶到n阶直接迈一步,1种走法
n-2阶到n阶可以直接上n阶,也可以先走到n-1阶再到n阶,2种走法,我们需要注意的是,后面的走法已经包含到了n-1到n阶里面了
n-3阶到n阶可以直接上n阶,也可以先到n-2再到n阶,可以先到n-1再到n阶,也可以一步一步来,但是后面的几种情况包含到了n-1阶到n阶和n-2阶到n阶的情况了
到n阶的问题就转化到小白到n-1阶的方式与n-2阶的方式与n-3的方式之和
,即f(n) = f(n-1)+f(n-2)+f(n-3)
#include<iostream>
using namespace std;
int Func(int n)
{
if (n == 0)return 0;
if (n == 1)return 1;
if (n == 2)return 2;
return Func(n - 1) + Func(n - 2) + Func(n - 3);
}
int main()
{
int n;
cin >> n;
cout << Func(n) << endl;
return 0;
}
在有空字符串的有序字符串数组中查找(二分查找)
假如说我给了一个字符串数组{ "a","","ac","","ad","b","","ba" },里面的空字串是随机分布的,我要找到里面"b"的下标,怎么办呢?我们用二分,找到中间的元素,如果说中间元素是空字符串,那我们就+1,如果+1还是空字符串我们还+1(上述也可以把+1换成-1,就是找到字符串能比较就行)
#include<iostream>
#include<stdlib.h>
#include<stdbool.h>
#include<string>
using namespace std;
int Fuc(string* a, int begin, int end, string key)
{
while (begin <= end)
{
int mid = (begin + end) / 2;
while (a[mid] == "")
{
mid += 1;
}
if (a[mid].compare(key) == -1)
{
begin = mid + 1;
}
else if (a[mid].compare(key) == 1)
{
end = mid - 1;
}
else {
return mid;
}
}
return -1;
}
int main()
{
string arr[] = { "a","","ac","","ad","b","","ba" };
int n = sizeof(arr) / sizeof(string);
string key = "b";
int index = Fuc(arr, 0, n - 1, key);
cout << arr[index];
return 0;
}
找最长连续递增子序列(双指针)
题意:假如说我给了一个数组{1,9,2,5,7,3,4,6,8,0},最大子序列是{3,4,6,8},写出程序找出来最大子序列
我们用双指针的快慢指针,慢指针先指向0,快指针先指向1,我们一开始设置一个index变量存放有序子序列的头索引,然后如果快指针比慢指针对应的值大,那就让快指针和慢指针都+1,count+1,如果小了,我们就让快指针等于慢指针,慢指针+1寻找下一个有序子序列
#include<iostream>
#include<stdlib.h>
#include<stdbool.h>
#include<string>
#include<vector>
using namespace std;
int main()
{
int a[] = { 1, 9, 2, 5, 7, 3, 4, 6, 8, 0 };
int slow = 0;
int fast = slow + 1;
int n = sizeof(a) / sizeof(int);
vector<int>count1;
vector<int>index1;
while(fast<n)
{
int count = 1;
int index = slow;
while(a[fast] > a[slow])
{
fast += 1;
slow += 1;
count += 1;
}
slow = fast;
fast += 1;
count1.push_back(count);
index1.push_back(index);
}
int maxi = count1[0];
int num = 0;
for (int i = 0; i < count1.size(); i++)
{
if (count1[i] > maxi)
{
maxi = count1[i];
num = i;
}
}
for (int i = index1[num]; i <index1[num]+maxi ; i++)
{
cout << a[i] << " ";
}
return 0;
}