一、今日知识点总结
-
递归的含义:就是函数自己调用自己。
-
递归的三个注意点
1).定义一个函数,这个函数会自己调用自己,但是每次传递的参数是不一样的。
2).递归一点要有出口,即满足条件后需要return,否则就成了死递归,导致栈溢出。
3).根据递归式来补充递归内容。(解递归问题建议都先写递推式。)
-
对递归深度要有个概念,深度过深会导致栈溢出。
-
可以采用尾递归的方式来解决,由深度造成的栈溢出。
-
能够使用递归来解决的问题,包含下面三个条件
1). 待求问题的解,可以分解成几个子问题的解
2).待求问题的解,和分解后的子问题,只有数据规模不同,求解思路完全一样。
3).存在递归中止条件,即有出口。
二、今日做题记录
第一题
给定一个整数 n
,返回 n!
结果中尾随零的数量。
提示 n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1
第一想法,先求阶乘再判断有多少了尾随零。我真这么干了。结果求阶乘的结果一直越界。阶乘的结果很大。
求因子,末尾有几个0,表示阶乘过程中乘以了几个10,二10的因子有5和2,就看存在几对5和2,偶数太多,就看包含了几个5的因子。
记录下求10以内的阶乘的递归方法
int getFactorial(int n){
if (n <= 1){
return 1;
}
return n*getFactorial(n-1);
}
求10以内的阶乘的尾递归方法
int getFactorial(int n,int res){
if (n<=1){
return res;
}
return getFactorial(n-1,n*res);
}
该题的题解
int trailingZeroes(int n){
if(n<5){
return 0;
}
return n/5+trailingZeroes(n/5);
}
第二题
给你一个非负整数 num
,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。
就是按要求去处理num,每处理一次,结果数目加1,当num==0时就可以输出0了。
int numberOfSteps(int num){
if(num == 0) {
return 0;
}
if(num & 1) { //奇数同1与运算,结果为1,表示奇数。为0表示偶数
return numberOfSteps(num-1)+1;
}else {
return numberOfSteps(num/2) + 1;
}
}
第三题
给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。
完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。
遍历整个二叉树,当子节点为空时,返回结果0,总的阶段数,等于左子树节点数+右子树节点数+本身。
int countNodes(struct TreeNode* root){
if(root == NULL) {
return 0;
}
return countNodes(root->left) + countNodes(root->right) + 1;
}
第四题
「力扣挑战赛」开幕式开始了,空中绽放了一颗二叉树形的巨型焰火。
给定一棵二叉树 root 代表焰火,节点值表示巨型焰火这一位置的颜色种类。请帮小扣计算巨型焰火有多少种不同的颜色。
int Hash[1024];
void transfer(struct TreeNode* root) {
if(root) {
Hash[root->val] = 1;
transfer(root->left);
transfer(root->right);
}
}
int numColor(struct TreeNode* root){
int i, sum = 0;
memset(Hash, 0, sizeof(Hash));
transfer(root);
for(i = 1; i <= 1000; ++i) {
if(Hash[i]) ++sum;
}
return sum;
}