【解题笔记】简单递归

1.阶乘后的零

给定一个整数 n ,返回 n! 结果中尾随零的数量。提示 n! = n * (n - 1) * (n - 2) * ... * 3 * 

int trailingZeroes(int n){
    if(n < 5)
        return 0;
    return n / 5 + trailingZeroes(n / 5);
}
//求n的阶乘后面0的个数,求10的因子,
//2 * 5 含2的倍数肯定大于5
//f(n) = n / 5 + n / 25 + n / 125 + n / 625 ...
//n/5 是有多少个5的倍数
//n/25 是有多少个25的倍数 = 个数乘以2是有多少个5的倍数
//n/125是有多少个125的倍数= 个数乘以3是有多少个5的倍数
//若n能除125,则n/5的个数中包含一份25的和一份125,则n/25 中包含125的
//所以一直加起来就能得到n / 5 < 5 时,将前面的全部加起来就得到了阶乘后的零

2.将数字变成0的操作次数

给你一个非负整数 num ,请你返回将它变成 0 所需要的步数。 如果当前数字是偶数,你需要把它除以 2 ;否则,减去 1 。

int numberOfSteps(int num){
    if(num == 0)
        return 0;
    if(num & 1){
        return 1 + numberOfSteps(num - 1);
    }
    else{
        return 1 + numberOfSteps(num / 2);
    }
}
//一个数按位与1等于1时,这个数是奇数,一个数按位与1等于0时,这个数是偶数
//使用递归 :
//    当数字为0,不需要操作,返回0
//    当数字为奇数,操作次数为1 + (num - 1)需要操作的次数
//    当数字为偶书时,操作次数为1 + (num / 2 )需要的次数

3.完全二叉树的节点个数

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */

int countNodes(struct TreeNode* root){
    if(root == NULL){
        return 0;
    }
    return countNodes(root->left) + countNodes(root->right) + 1;
}
//当根指针为空指针时,节点的个数为0
//当根指针不是空指针时,节点的个数为1 + 这个节点下左边的个数 + 这个节点右边的个数

4.开幕式焰火

「力扣挑战赛」开幕式开始了,空中绽放了一颗二叉树形的巨型焰火。
给定一棵二叉树 root 代表焰火,节点值表示巨型焰火这一位置的颜色种类。请帮小扣计算巨型焰火有多少种不同的颜色

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */
int Hash[1001];
void transfer(struct TreeNode *root){
    if(root){
        Hash[root->val] = 1;
        transfer(root->left);
        transfer(root->right);
    }
}
int numColor(struct TreeNode* root){
    int i = 0, sum = 0;
    memset(Hash, 0, sizeof(Hash));
    transfer(root);
    for(i = 0; i < 1001; i++){
        if(Hash[i]){
            sum++;
        }
    }
    return sum;
}
//计算开幕式焰火的类型,不同的值代表不同焰火
//先设置一个哈希数表,将其全部设置为0,然后遍历二叉树,将二叉树的那个值对应的下标的数字设为,非零,统计数组中非0的个数就能得到焰火的类型
//当指针为空指针时,表示后面没有节点,在往下走没有数字,终止

5.整数替换

给定一个正整数 n ,你可以做如下操作:

如果 n 是偶数,则用 n / 2替换 n 。
如果 n 是奇数,则可以用 n + 1或n - 1替换 n 。
n 变为 1 所需的最小替换次数是多少?

int integerReplacement(int n){
    if(n == 2147483647)
        return 32;
    // (long)n;
    if(n == 1)
        return 0;
    if(n & 1){
        if((n & 3) == 3 && n != 3){
            return 1 + integerReplacement(n + 1);
        }
        else
            return 1 + integerReplacement(n - 1);
    }
    else{
        return 1 + integerReplacement(n / 2);
    }
}
//当n为2147483647时,加1时会造成数组越界,所以直接返回这个值
//当n是奇数,且是3的倍数时,进行的操作是加1,否则为减1
//当n是偶数,进行操作是除2;
//n为奇数时,可以直接进行两部操作,重新变成一个数
//(n + 1) / 2     (n - 1 ) / 2  把这个数变成偶数要好一些
//奇数的公式 : 2n + 1 带入的结果是  n + 1或 n ,结果奇偶性取决于n的奇偶性
//             不妨令 n = 2k  或 2k + 1代表奇偶
//    带入后式子为:原数为 4k + 1  或 4k + 3
//    就可以转换,4k + 3 时,加1,4k + 1时,减1
//    当为3时,直接减一除2
//当n % 4 = 1 时,
//    n应该变为 n - 1
//当n % 4 = 3 时
//    n应该变为 n + 1
// 7 -- 8 -- 4 -- 2 -- 1
// 7 -- 6 -- 3 -- 2 -- 1
// 11 -- 12 -- 6 -- 3 -- 2 -- 1
// 11 -- 10 -- 5 -- 4 -- 2 -- 1
// 15 -- 16 -- 8 -- 4 -- 2 -- 1
// 15 -- 14 -- 7 -- 8 -- 4 -- 2 -- 1
n为4k + 1时,最好-1(2k) -- k(3);假设加1
    经过两次变换后 : 2k + 1  2
            加一  :(k + 1)   4(减一得到这个结果是4步)
            减一  :(k)       4(减一得到这个结果是3步)
n为4k + 3时,最好+1;假设减一
    经过两次变换后:2k + 1 
            加一 :k + 1(4)(加一需要3步)(2k + 1 ---- k + 1)
            减一 :k    (4)(加一需要4步)(2k + 1 ---- 2k --- k)

6.二叉数搜索范围的和

给定二叉搜索树的根结点 root,返回值位于范围 [low, high] 之间的所有结点的值的和。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


int rangeSumBST(struct TreeNode* root, int low, int high){
    if(root == NULL){
        return 0;
    }
    if(root->val > high){
        return rangeSumBST(root->left, low, high); 
    }
    if(root->val < low){
        return rangeSumBST(root->right, low, high);
    }
    return root->val + rangeSumBST(root->left, low, high) + rangeSumBST(root->right, low, high);
}
//求符合条件的二叉搜索数的和,
//二叉树的左边是递减的,右边是递增的,
//只要那个数比最大的大,就从左边找符合条件的
//只要那个数比最小的小,就从右边找符合条件的
//返回所有符合条件数的和

7.二叉树的深度

输入一棵二叉树的根节点,求该树的深度。从根节点到叶节点依次经过的节点(含根、叶节点)形成树的一条路径,最长路径的长度为树的深度。

/**
 * 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;
    }
    int left = maxDepth(root->left);
    int right = maxDepth(root->right);
    if(left > right){
        return left + 1;
    }
    return right + 1;
}
//如果是空指针,返回0;
//如果左边的深度大于右边,深度就是左边+1
//若果右边的深度大于左边,深度就是右边+1

8.二叉树的最大深度

给定一个二叉树,找出其最大深度。

二叉树的深度为根节点到最远叶子节点的最长路径上的节点数。

说明: 叶子节点是指没有子节点的节点

/**
 * 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;
    }
    int left = maxDepth(root->left);
    int right = maxDepth(root->right);
    if(left > right){
        return left + 1;
    }
    return right + 1;
}

9.翻转二叉树

翻转一棵二叉树。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     struct TreeNode *left;
 *     struct TreeNode *right;
 * };
 */


struct TreeNode* invertTree(struct TreeNode* root){//函数返回的是结构体指针root
    if(root == NULL){//如果是空指针,返回0;
        return 0;
    }
    struct invertTree *left = invertTree(root->left);//将root->left 的指针赋给left
    struct invertTree *right = invertTree(root->right);//将root->right的指针赋给right
    root->left = right;//交换位置
    root->right = left;//
    return root;
}

10.所有路径

给定一个有 n 个节点的有向无环图,用二维数组 graph 表示,请找到所有从 0 到 n-1 的路径并输出(不要求按顺序)。

graph 的第 i 个数组中的单元都表示有向图中 i 号节点所能到达的下一些结点(译者注:有向图是有方向的,即规定了 a→b 你就不能从 b→a ),若为空,就是没有下一个节点了。

11.所有路径

给你一个有 n 个节点的 有向无环图(DAG),请你找出所有从节点 0 到节点 n-1 的路径并输出(不要求按特定顺序)

二维数组的第 i 个数组中的单元都表示有向图中 i 号节点所能到达的下一些节点,空就是没有下一个结点了。

译者注:有向图是有方向的,即规定了 a→b 你就不能从 b→a 。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值