今天是九日集训第八天,我会记录一下学习内容和题解,争当课代表0.0.
链接:《LeetCode零基础指南》(第九讲) 简单递归
作者简介:一个从工业设计改行学嵌入式的年轻人
✨联系方式:2201891280(QQ)
⏳全文大约阅读时间: 20min
套娃生万物,而递归就是函数自己调用自己。
递归需要记住三点内容:
- 要实现一个函数,这个函数会自己调用自己,并且每次调用,函数传参是不一样的。
- 递归一定要有出口,即满足一定条件后需要
return
,否则就可能出现死递归(引起栈溢出)。- 根据递归式来补充你的递归调用内容。
我们知道,阶乘即:
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)
1. 实现一个函数
int JieCheng(int n){ }
2. 递归出口
int JieCheng(int n) { if(n <= 1) { return 1; } }
3. 递推关系
int JieCheng(int n) { if(n <= 1) { return 1; } return n * JieCheng(n-1); }
f(5) = 5 * f(4) = 5 * (4 * f(3)) = 5 * (4 * (3 * f(2))) = 5 * (4 * (3 * (2 * f(1)))) = 5 * (4 * (3 * (2 * 1))) = 5 * (4 * (3 * 2)) = 5 * (4 * 6) = 5 * 24 = 120
172. 阶乘后的零
题目描述
给定一个整数
n
,返回n!
结果中尾随零的数量。
提示n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1
思路
因为阶乘的0的数量其实取决于这个数中10的因子个数。但是
10 = 5 *2
。其中2的数量会比5的数量多,所以只需要5因子的数量就好了。其中5的倍数贡献一个。25贡献两个,125贡献三个,但是25还是5的倍数,所以只需要再算一次就好了。 125也是一样的道理,125算一个就好了。
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
代表焰火,节点值表示巨型焰火这一位置的颜色种类。请帮小扣计算巨型焰火有多少种不同的颜色。
思路
利用hash表来做标记,然后进行先根遍历。然后最后算数量。
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
所需的最小替换次数是多少?
思路
如果是偶数,毫无疑问是直接除以2就好了。
如果是奇数:
- 如果这个奇数是k = 4*n+1那么(k-1)/2会得到更小的值。
- 如果这个奇数是k = 4*n+3 那么(k+1)/4会得到最小的值,但是有一个特殊情况就是n=3
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
的路径并输出(不要求按顺序)。
graph
的第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;
}
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;
}
今天结束了六级,也结束了数字集成电路的作业,所以最近有亿点点时间可以更新,所以要开算法坑了,有一起的同学们么?首页见!