一.知识点
.递归含义
套娃生万物,而递归就是函数自己调用自己。
递归需要记住三点内容:
要实现一个函数,这个函数会自己调用自己,并且每次调用,函数传参是不一样的。
递归一定要有出口,即满足一定条件后需要return,否则就可能出现死递归(引起栈溢出)。
根据递归式来补充你的递归调用内容。
2.递归调用阶乘
我们知道,阶乘即:
n ! = n ∗ ( n − 1 ) ∗ ( n − 2 ) ∗ . . . ∗ 3 ∗ 2 ∗ 1 n! = n *(n-1)*(n-2)*...*3*2*1 n!=n∗(n−1)∗(n−2)∗...∗3∗2∗1
我们如果想用递归进行计算,就需要转换为递推式,如下:
n ! = n ∗ ( n − 1 ) ! n! = n*(n-1)! n!=n∗(n−1)!
我们可以得出一下的递归式:
f ( n ) = n f ( n − 1 ) f(n) = n f(n-1) f(n)=nf(n−1)
课后习题
172. 阶乘后的零
给定一个整数
n
,返回n!
结果中尾随零的数量。
提示n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1
int trailingZeroes(int n){
int ans = 0;
for(int i = 5;i <= n;i*=5){
ans += n / i;
}
return ans;
}
1342. 将数字变成 0 的操作次数
题目描述
给你一个非负整数
num
,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。
int numberOfSteps(int num){
if(num == 0) return 0;
else if( num & 1 == 1) return numberOfSteps(num -1) +1;
else return numberOfSteps(num / 2) +1;
}
222. 完全二叉树的节点个数
题目描述
给你一棵 完全二叉树 的根节点 root,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h层,则该层包含 1~ 2h个节点。
void previsit(struct TreeNode *root,int *ans){
if(root){
(*ans) ++;
previsit(root->left,ans);
previsit(root->right,ans);
}
}
int countNodes(struct TreeNode* root){
int ans = 0;
previsit(root,&ans);
return ans;
}
LCP 44. 开幕式焰火
题目描述
「力扣挑战赛」开幕式开始了,空中绽放了一颗二叉树形的巨型焰火。
给定一棵二叉树root
代表焰火,节点值表示巨型焰火这一位置的颜色种类。请帮小扣计算巨型焰火有多少种不同的颜色。
int hash[1001];
void get123(struct TreeNode * );
int numColor(struct TreeNode* root){
int ans = 0;
memset(hash,0,sizeof(hash));
get123(root);
for(int i = 0; i < 1001; ++i){
if(hash[i]) ans++;
}
return ans;
}
void get123(struct TreeNode * root){
if(root){
if(root ->left) get123(root->left);
hash[root->val]++;
if(root->right) get123(root->right);
}
}
397. 整数替换
题目描述
给定一个正整数
n
,你可以做如下操作:
- 如果
n
是偶数,则用n / 2
替换n
。- 如果
n
是奇数,则可以用n + 1
或n - 1
替换n
。
n
变为1
所需的最小替换次数是多少
int integerReplacement(int n){
int ans = 0;
while(n != 1){
if(n % 2 == 0) n /= 2;
else if(n % 4 == 1){
n /= 2;
ans++;
}
else{
if(n == 3) n = 1;
else n = n/2 + 1;
ans++;
}
ans++;
}
return ans;
}
938. 二叉搜索树的范围和
题目描述
给定二叉搜索树的根结点 root,返回值位于范围
[low, high]
之间的所有结点的值的和
void previsit(struct TreeNode *root,int low,int high,int *ans){
if(root){
if(root->val >= low && root->val <= high) (*ans) += root->val;
previsit(root->left,low,high,ans);
previsit(root->right,low,high,ans);
}
}
int rangeSumBST(struct TreeNode* root, int low, int high){
int ans = 0;
previsit(root,low,high,&ans);
return ans;
}
剑指 Offer 55 - I. 二叉树的深度
题目描述
输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。
例如:
给定二叉树 [3,9,20,null,null,15,7]
void previsit(struct TreeNode *root,int *max,int ceng){
if(root){
ceng ++;
if(ceng > *max) *max = ceng;
previsit(root->left,max,ceng);
previsit(root->right,max,ceng);
}
}
int maxDepth(struct TreeNode* root){
int max = 0;
previsit(root,&max,0);
return max;
}
104. 二叉树的最大深度
题目描述
给定一个二叉树,找出其最大深度。
二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。
说明: 叶子节点是指没有子节点的节点。
示例:
给定二叉树[3,9,20,null,null,15,7]
void previsit(struct TreeNode *root,int *max,int ceng){
if(root){
ceng ++;
if(ceng > *max) *max = ceng;
previsit(root->left,max,ceng);
previsit(root->right,max,ceng);
}
}
int maxDepth(struct TreeNode* root){
int max = 0;
previsit(root,&max,0);
return max;
}
226. 翻转二叉树
题目描述
翻转一棵二叉树
struct TreeNode* invertTree(struct TreeNode* root){
if(root){
struct TreeNode *temp;
temp = root->left;
root->left = root->right;
root->right = temp;
invertTree(root->left);
invertTree(root->right);
}
return root;
}
剑指 Offer II 110. 所有路径
题目描述
给定一个有
n
个节点的有向无环图,用二维数组graph
表示,请找到所有从0
到n-1
的路径并输出(不要求按顺序)void dfs(int x,int n, int **graph, int *graphColSize,int *returnSize,int **returnColumnSizes,int **ans,int *temp,int tempsize){ if(x == n){ int *tmp = malloc(sizeof(int)*tempsize); memcpy(tmp,temp,sizeof(int) * tempsize); ans[*returnSize] = tmp; (*returnColumnSizes)[(*returnSize)++] = tempsize; return; } for(int i = 0; i < graphColSize[x];i++){ int y = graph[x][i]; temp[tempsize++] = y; dfs(y,n, graph , graphColSize, returnSize,returnColumnSizes,ans,temp,tempsize); tempsize--; } } int** allPathsSourceTarget(int** graph, int graphSize, int* graphColSize, int* returnSize, int** returnColumnSizes){ int **ans; int temp[15]; int tempsize = 0; temp[tempsize++] = 0; ans = malloc(sizeof(int *) * (1<<13)); *returnSize = 0; (*returnColumnSizes) = malloc(sizeof(int) *(1<<13)); dfs(0,graphSize - 1, graph , graphColSize, returnSize,returnColumnSizes,ans,temp,tempsize); return ans; }
797. 所有可能的路径
题目描述
给你一个有 n 个节点的 有向无环图(DAG),请你找出所有从节点 0 到节点 n-1 的路径并输出(不要求按特定顺序)
二维数组的第 i 个数组中的单元都表示有向图中 i 号节点所能到达的下一些节点,空就是没有下一个结点了。
译者注:有向图是有方向的,即规定了 a→b 你就不能从 b→a
void dfs(int x,int n, int **graph, int *graphColSize,int *returnSize,int **returnColumnSizes,int **ans,int *temp,int tempsize){ if(x == n){ int *tmp = malloc(sizeof(int)*tempsize); memcpy(tmp,temp,sizeof(int) * tempsize); ans[*returnSize] = tmp; (*returnColumnSizes)[(*returnSize)++] = tempsize; return; } for(int i = 0; i < graphColSize[x];i++){ int y = graph[x][i]; temp[tempsize++] = y; dfs(y,n, graph , graphColSize, returnSize,returnColumnSizes,ans,temp,tempsize); tempsize--; } } int** allPathsSourceTarget(int** graph, int graphSize, int* graphColSize, int* returnSize, int** returnColumnSizes){ int **ans; int temp[15]; int tempsize = 0; temp[tempsize++] = 0; ans = malloc(sizeof(int *) * (1<<13)); *returnSize = 0; (*returnColumnSizes) = malloc(sizeof(int) *(1<<13)); dfs(0,graphSize - 1, graph , graphColSize, returnSize,returnColumnSizes,ans,temp,tempsize); return ans; }