递归小谈
考虑以下的递归公式:
\[ n! = \begin{cases} 1 & \text{if }
n = 0 \\ n \times (n - 1)! & \text{otherwise} \end{cases}
\]
用C语言表示如下:
1 2 3 4 5 6 7 8 9 10 11
| int factorial(int n) { if (n == 0) { return 1; } else { return n * factorial(n - 1); } }
|
递归思维
用递归解决问题需要两个步骤: 首先,确定如何解决简单情况的问题。
● 这称为基本情况(base case)。
其次,确定如何将较大情况分解为较小的实例。
● 这称为递归步骤(recursive step)。
1 2 3 4 5 6 7 8 9
| if (问题非常简单) { return 解决方案; } else { return 整体解决方案; }
|
现在试试把以下代码改写成递归的形式:
1 2 3 4 5 6 7 8
| int sumOfDigitsOf(int n) { int result = 0; while (n > 0) { result += (n % 10); n /= 10; } return result; }
|
示例:
1 2 3 4 5 6 7 8 9
| int sumOfDigitsOf(int n) { if (n == 0) { return 0; } return (n % 10) + sumOfDigitsOf(n / 10); }
|
数根问题
数根是指通过反复将数字的各位数相加,直到得到一个个位数为止。
5 的数根是什么? 5 已经是一个个位数,所以答案是 5。
27 的数根是什么? 2 + 7 = 9。 答案是 9。
137 的数根是什么?用代码来解决。
1 2 3 4 5 6 7 8 9
| int digitalRoot(int n) { if (n < 10) { return n; } return digitalRoot(n % 10 + digitalRoot(n / 10)); }
|
现在尝试利用递归来逆转字符串:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| #include <iostream> #include <string>
using namespace std;
string reverseString(string s) { if (s.empty() || s.length() == 1) { return s; } return reverseString(s.substr(1)) + s[0]; }
void solve() { string s; cin >> s;
cout << s.length() << endl;
for(auto fw : s) { cout << fw << ' '; } cout << endl;
cout << reverseString(s) << endl; }
|
用标准库的做法
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| #include <iostream> #include <string> #include <algorithm>
using namespace std;
void solve() { string s; cin >> s;
cout << s.length() << endl;
for(auto fw : s) { cout << fw << ' '; } cout << endl;
reverse(s.begin(), s.end());
for(auto fw : s) { cout << fw; } cout << endl;
return; }
|