【解题报告】《九日集训》(第九天)

语言:C++

172. 阶乘后的零

172. 阶乘后的零

给定一个整数 n ,返回 n! 结果中尾随零的数量。

提示 n! = n * (n - 1) * (n - 2) * ... * 3 * 2 * 1

示例 1:

输入:n = 3
输出:0
解释:3! = 6 ,不含尾随 0

个人认为这个题最难的点在于大数的处理

拿到这个题的第一想法就是拿sum保存n!

但是0<=n<=10000,显然long long类型的sum都行不通

看了题解

找5的倍数真的是绝,只有n是5的倍数才会有末尾0的出现,5*任何偶数都会出现末尾0

将所有5的倍数x拆分为5*y(即y个5,会有y个0出现)

同时y也有可能是5的倍数,所以return的是n / 5 + trailingZeroes(n / 5)

不断递归,直至n<5

class Solution 
{
public:
    int trailingZeroes(int n) 
    {
        if (n < 5)
            return 0;
        return n / 5 + trailingZeroes(n / 5);
    }
};

照着递归,写了迭代

class Solution
{
public:
	int trailingZeroes(int n)
	{
		int tmp = 0;
		while (n)
		{
			if (n < 5)
				break;
			tmp += n / 5;
			n /= 5;
		}
		return tmp;
	}
};

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

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

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

示例 1:

输入:num = 14
输出:6
解释:
步骤 1) 14 是偶数,除以 2 得到 7 。
步骤 2) 7 是奇数,减 1 得到 6 。
步骤 3) 6 是偶数,除以 2 得到 3 。
步骤 4) 3 是奇数,减 1 得到 2 。
步骤 5) 2 是偶数,除以 2 得到 1 。
步骤 6) 1 是奇数,减 1 得到 0 。

class Solution 
{
public:
    int numberOfSteps(int num)
    {
        int tmp = 0;
        while (num)
        {
            if (num & 1)
            {
                num -= 1;
            }
            else
            {
                num /= 2;
            }
            ++tmp;
        }
        return tmp;
    }
};

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

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

给你一棵 完全二叉树 的根节点 root ,求出该树的节点个数。

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

示例 1:

img

输入:root = [1,2,3,4,5,6]
输出:6

递归

class Solution 
{
public:
    int countNodes(TreeNode* root) 
    {
        if (root == NULL)
            return 0;
        return 1 + countNodes(root->left) + countNodes(root->right);
    }
};

迭代:层序遍历

class Solution
{
public:
	int countNodes(TreeNode* root)
	{
		int tmp = 0;
		queue<TreeNode*> que;
		if (root != NULL)
		{
			que.push(root);
			tmp++;
		}
		while (!que.empty())
		{
			int size = que.size();
			for (int i = 0; i < size; i++)
			{
				TreeNode* node = que.front();
				que.pop();
				if (node->left)
				{
					que.push(node->left);
					tmp++;
				}
				if (node->right)
				{
					que.push(node->right);
					tmp++;
				}
			}
		}
		return tmp;
	}
};

LCP 44. 开幕式焰火

可dfs

LCP 44. 开幕式焰火

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

示例 1:

输入:root = [1,3,2,1,null,2]

输出:3

解释:焰火中有 3 个不同的颜色,值分别为 1、2、3

层序遍历

不得不说,还是喜欢在二叉树类的题目中使用层序遍历

class Solution
{
public:
    int numColor(TreeNode* root) 
    {
        unordered_set<int>set;
        queue<TreeNode*>que;
        if (root != NULL)
        {
            que.push(root);
        }
        while (!que.empty())
        {
            int size = que.size();
            for (int i = 0; i < size; ++i)
            {
                TreeNode* node = que.front();
                set.insert(que.front()->val);
                que.pop();
                if (node->left)
                {
                    que.push(node->left);
                }
                if (node->right)
                {
                    que.push(node->right);
                }
            }
        }
        return set.size();
    }
};

评论区看到的dfs

目前不懂这个算法

class Solution
{
public:
	unordered_set<int>set;

	void dfs(TreeNode* root)
	{
		if (root)
			set.insert(root->val);
		if (root->left)
			dfs(root->left);
		if (root->right)
			dfs(root->right);
	}

	int numColor(TreeNode* root)
	{
		dfs(root);
		return set.size();
	}
};

397. 整数替换

397. 整数替换

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

  1. 如果 n 是偶数,则用 n / 2替换 n
  2. 如果 n 是奇数,则可以用 n + 1n - 1替换 n

n 变为 1 所需的最小替换次数是多少?

示例 1:

输入:n = 8
输出:3
解释:8 -> 4 -> 2 -> 1

看了很多题解,只有这个理解了

首先如果一个数是偶数的时候,不断除以二就是最优方案。

如果是奇数,此时只有两种操作:+1 或 -1。
正确的做法不是判断该数是否是 2 的幂次方(悲伤呀,我自己的写法就是判断n+1和n-1哪个会是2的幂次方)。而是应该看这个数最低位是否有 至少 2 个连续的 1。

因为在最低位有多个连续 1 的情况下,+1,能够同时消去多个 1,然后在前面补一位 1,在最低位到补的这一个 1 之间都是 0,可以直接通过不断右移得到。

而如果在这种情况下 -1,之后每右移 1 位后都会遇到这些连续的 1,这样每右移一位后都会比之前多一步减 1 的操作。

如果最后只有 2 个连续的 1,那么 +1 和 -1 的最终操作数是一样的。大于 2 个的时候,一定是 +1 操作数少。
唯一特例:3。只有 3 的时候,是直接 -1 最优。 3 → 2 → 1 优于 3 → 4 → 2 → 1。

另外注意当 n == INT_MAX 时,+1 会爆 int。

class Solution
{
public:
	int integerReplacement(int n)
	{
		int tmp = 0;
		long num = n;
		while (num > 1)
		{
			if (num&1)
			{
				if (num != 3 && (num >> 1) & 1)
				{
					num += 1;
				}
				else
				{
					num -= 1;
				}
			}
			else
			{
				num /= 2;
			}
			tmp++;
		}
		return tmp;
	}
};

938. 二叉搜索树的范围和

938. 二叉搜索树的范围和

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

示例 1:

img

输入:root = [10,5,15,3,7,null,18], low = 7, high = 15
输出:32

层序遍历

class Solution 
{
public:
    int rangeSumBST(TreeNode* root, int low, int high)
    {
        queue<TreeNode*>que;
        if (root)
        {
            que.push(root);
        }
        int tmp=0;
        while (!que.empty())
        {
            int size = que.size();
            for (int i = 0; i < size; i++)
            {
                TreeNode* node = que.front();
                que.pop();
                if (node->val >= low && node->val <= high)
                {
                    tmp += node->val;
                }
                if (node->left)
                    que.push(node->left);
                if (node->right)
                    que.push(node->right);
            }
        }
        return tmp;
    }
};

剑指 Offer 55 - I. 二叉树的深度

剑指 Offer 55 - I. 二叉树的深度

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

例如:

给定二叉树 [3,9,20,null,null,15,7]

​ 3

/
9 20
/
15 7

返回它的最大深度 3 。

层序遍历

class Solution 
{
public:
    int maxDepth(TreeNode* root) 
    {
        queue<TreeNode*>que;
        if (root)
            que.push(root);
        int tmp = 0;
        while (!que.empty())
        {
            tmp++;
            int size = que.size();
            for (int i = 0; i < size; i++)
            {
                TreeNode* node = que.front();
                que.pop();
                if (node->left)
                    que.push(node->left);
                if (node->right)
                {
                    que.push(node->right);
                }
            }
        }
        return tmp;
    }
};

104. 二叉树的最大深度

104. 二叉树的最大深度

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

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

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

示例:
给定二叉树 [3,9,20,null,null,15,7]

    3
   / \
  9  20
    /  \
   15   7

返回它的最大深度 3 。

层序遍历

class Solution 
{
public:
    int maxDepth(TreeNode* root) 
    {
        if (root == NULL)
            return 0;
        queue< TreeNode*>que;
        que.push(root);
        int k = 0;
        while (!que.empty())
        {
            int len = que.size();
            for (int i = 0; i < len; i++)
            {
                TreeNode* node = que.front();
                que.pop();
                if (node->left)
                    que.push(node->left);
                if (node->right)
                    que.push(node->right);
            }
            k++;
        }
        return k;
    }
};

226. 翻转二叉树

226. 翻转二叉树

翻转一棵二叉树。

示例:

输入:

     4
   /   \
  2     7
 / \   / \
1   3 6   9

输出:

     4
   /   \
  7     2
 / \   / \
9   6 3   1

修改递归顺序

class Solution 
{
public:
    TreeNode* invertTree(TreeNode* root) 
    {
        if (root == NULL) return root;
        swap(root->left, root->right);  // 中
        invertTree(root->left);         // 左
        invertTree(root->right);        // 右
        return root;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值