在C语言的学习过程中,我们时常遇到一些特殊的问题,这些问题一步一步解决,且这些步骤都是这个问题的上一步或下一步(语文不好,不太会形容,555),这时候,我们就可以使用递归。
递归其实就是函数自己调用自己链表的问题与一些树的问题常用它来解决。著名的深度优先搜索(DFS)就可以通过递归实现。
接下来给出几个简单例题帮助大家理解:
例1:非常经典的斐波那契数
#include <stdio.h>
int fibonacci(int n)
{
if(n <= 2) {
return 1;//第一、二个都是1。
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}//每个斐波那契数是它前两个的和,用递归来实现。
}
int main(void) {
int n;
printf("请输入你想输出第几项的斐波那契数:\n");
scanf("%d", &n);
printf("%d\n", fibonacci(n));
return 0;
}
例2:非常简单的一道二叉树题目
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
int maxDepth(struct TreeNode *root) {
if (root == NULL) return 0;
return fmax(maxDepth(root->left), maxDepth(root->right)) + 1;
}//每个结点的高度是它下面两个高度的最大值再加一,用递归实现。
例3:又是一道二叉树的题:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* struct TreeNode *left;
* struct TreeNode *right;
* };
*/
bool hasPathSum(struct TreeNode *root, int sum) {
if (root == NULL) {
return false;
}//没有路,返回false。
if (root->left == NULL && root->right == NULL) {
return sum == root->val;
}//接下来无路可走,从头走到结束了,如果总和等于target,则返回true,找到,否则返回false。
return hasPathSum(root->left, sum - root->val) || hasPathSum(root->right, sum - root->val);
}//最后递归,分别向左右两边找。
例4:全排列问题(深度优先搜索)
力扣46.全排列
给定一个 没有重复 数字的序列,返回其所有可能的全排列。
/**
* Return an array of arrays of size *returnSize.
* The sizes of the arrays are returned as *returnColumnSizes array.
* Note: Both returned array and *columnSizes array must be malloced, assume caller calls free().
*/
int cnt;
void dfs(int step, int* nums, int numsSize, int** ret, int* path, bool* book) {
//step先从0开始
int i;
if (step == numsSize) {
//找到一种排列方式。
ret[cnt] = (int*)malloc(sizeof(int) * numsSize);
for(int i=0;i<numsSize;++i){
ret[cnt][i]=path[i];
}
//放到答案的数组里
cnt++;//计数器加1
return;
}
for (i = 0; i < numsSize; i++) {
if (book[i]) {
continue;
//这个值被用过,找下一个。
}
//值没被用过,那这次就把它加上。
path[step] = nums[i];
book[i] = true;
//这次用了这个值,接下来找下一个位置的。
dfs(step + 1, nums, numsSize, ret, path, book);
//注意step + 1
book[i] = false;
//递归到最后一步跳出来了,这个值相当于上一次用过了,下一次还要用,book归位,表示还未用,这步十分关键。
}
return;
}
int** permute(int* nums, int numsSize, int* returnSize, int** returnColumnSizes) {
cnt = 0;//计数器最开始为0
*returnSize = 1;
for (i = 1; i <= numsSize; i++) {
*returnSize *= i;
}//数学方式计算应该有多少种全排列。
*returnColumnSizes = (int*)malloc(sizeof(int) * (*returnSize));
for (int i = 0; i < (*returnSize); i++) {
(*returnColumnSizes)[i] = numsSize;
}
bool* book = (bool*)calloc(numsSize, sizeof(bool));
//book用来判断一个值是否被用过。
int** ret = (int**)malloc(sizeof(int*)*(*returnSize));
int* path = (int*)malloc(sizeof(int) * numsSize);
//初始化一个路径数组用来记录每一次全排列。
dfs(0, nums, numsSize, ret, path, book);
return ret;
}