LeetCode——Weekly Contest 315&317

LeetCode周赛第315&317场记录

第315场周赛值得学习的点不是很多,这里只是简单地总结一下。

前三题都非常简单,两道middle题都是关于数字反转的,使用标准库函数首先将其转为字符串翻转过来之后stoi返回即可高效地完,核心代码如下,其余的部分都是暴力法即可:

int reverseNumber(int Num)	// 反转一个数字的函数,使用标准库实现
{
	string S = to_string(Num);
	reverse(S.begin(), S.end());
	return stoi(S);
}

第316场周赛因为要开组会,没有打。


接下来是317场周赛的部分:

6220. 可被三整除的偶数的平均值

在这里插入图片描述
第一题很简单,但是要注意的地方在于我们要求平均数的数字必须满足以下两个条件
1.可以被3整除
2.必须是偶数

另外要注意,如果没有这样的数字,那么计数值为0,但不可以除以0

完整的代码如下:

class Solution {
public:
    int averageValue(vector<int>& nums) 
    {
        int Sum = 0, Counter = 0;
		for(auto Each : nums)
			if((Each % 3 == 0) && (Each % 2 == 0))
			{
				Sum += Each;
				++Counter;
			}
		
		return Counter == 0 ? 0 : (Sum / Counter);
    }
};

6221. 最流行的视频创作者

在这里插入图片描述
第二题主要考查阅读理解能力对数据进行处理和排序,思路上没有什么难度,稍微有点费代码,直接给出含有注释的代码

class Solution {
public:
    vector<vector<string>> mostPopularCreator(vector<string>& creators, vector<string>& ids, vector<int>& views) {
        int n = creators.size(), MaxViews = 0;
		vector<vector<string>> Ans;
		vector<string> TopCreators; // 总播放量最高的创作者集合,可能不止一个
		unordered_map<string, long long> ViewCounter;// 创作者和他们对应的播放量总量
		unordered_map<string, pair<string, int>> TopVideos;	//创作者和他们对应的最高播放次数的作品
		for(int i = 0 ; i < n ; ++i)
		{
			ViewCounter[creators[i]] += views[i];	// 累计创作者播放总量
			if(TopVideos.count(creators[i]) == 0)	// 如果当前创作者播放量最高的视频没被记录
				TopVideos[creators[i]] = make_pair(ids[i], views[i]);	
			else if(TopVideos[creators[i]].second < views[i]) // 或者已经被记录但是新的作品播放量更高
				TopVideos[creators[i]] = make_pair(ids[i], views[i]);
			else if(TopVideos[creators[i]].second == views[i] && TopVideos[creators[i]].first > ids[i]) // 或者播放量一样多但是新的作品名字字典序更小
				TopVideos[creators[i]] = make_pair(ids[i], views[i]);	// 这三种情况都应该将新的记录插入哈希表
			else continue;
		}
			
		/* 找出播放总量最高的创作者,可能不止一个 */
		for(auto iter = ViewCounter.begin() ; iter != ViewCounter.end() ; ++iter)
		{
			if(iter->second > MaxViews)
			{
				TopCreators.clear();
				TopCreators.push_back(iter->first);
				MaxViews = iter->second;
			}
			else if(iter->second == MaxViews)
				TopCreators.push_back(iter->first);
		}
		/* 将这几个播放量最高的创作者的代表作加入答案,至此结束 */
		for(auto& Each : TopCreators)
			Ans.push_back({Each, TopVideos[Each].first});
		
		return Ans;
		
    }
};

6222. 美丽整数的最小增量

在这里插入图片描述
这道题我一开始使用的是暴力法,但是这样一定会超时,因为这道题最终的答案可能会很大,超过 1 0 8 10^8 108。所以这道题使用暴力法从0开始一点点试下去一定会超时,这是一个基本的分析。

这道题还是应该使用模拟+贪心来解决,贪心的思路在比赛时我也想到了,但是我当时不知道该怎么处理进位,其实只需要对原先的数字+1就可以了,这在以下的代码中会集中展示。

class Solution {
	/*以下这个函数用来计算一个数字中各个数位上的数字之和,很简单*/
	int getBitSum(long long x)	// at most 12 times
	{
		int Ans = 0;
		while(x)
		{
			Ans += (x % 10);
			x /= 10;
		}
		return Ans;
	}
	
public:
    long long makeIntegerBeautiful(long long n, int target) {
		long long Ans = 0, Base = 1;
		/*贪心法:如果当前剩余数字各位之和仍大于target,那么循环继续*/
		while(getBitSum(n) > target)
		{
			Ans += (10 - (n % 10)) * Base;	// Ans应该保证与原先的n相加之后每一位上都可以向更高位进位,比如原先n的某位是1,那么Ans对应位应该是9
			n /= 10;	// 本质是模拟加法运算过程,这个数字加上Ans的运算完成之后n的当前位一定为0,对结果没有贡献,那么直接删除这一位
			n++;		// 因为还有向更高位的进位,所以对n加一
			Base *= 10;	// Base乘10,因为下一位一定要在更高位
		}
		return Ans;
	}
};

这道题总的代码量不大,但思路其实还是很巧妙的。

6223. 移除子树后的二叉树高度

在这里插入图片描述
这道题还是挺难的,需要两趟DFS,第一趟DFS是为了求每个子树的高度,并且记录在哈希表里。第二趟DFS就是为了求出删去每个子树时剩余部分的最大高度,结果也记录在一张哈希表里,随后就是直接回答查询即可。

这里直接给出灵茶山艾府的代码,作为记录:

lass Solution {
public:
    vector<int> treeQueries(TreeNode *root, vector<int> &queries) {
        unordered_map<TreeNode*, int> height; // 每棵子树的高度
        function<int(TreeNode*)> get_height = [&](TreeNode *node) -> int {
            return node ? height[node] = 1 + max(get_height(node->left), get_height(node->right)) : 0;
        };
        get_height(root);

        int res[height.size() + 1]; // 每个节点的答案
        function<void(TreeNode*, int, int)> dfs = [&](TreeNode *node, int depth, int rest_h) {
            if (node == nullptr) return;
            ++depth;
            res[node->val] = rest_h;
            dfs(node->left, depth, max(rest_h, depth + height[node->right]));
            dfs(node->right, depth, max(rest_h, depth + height[node->left]));
        };
        dfs(root, -1, 0);

        for (auto &q : queries) q = res[q];
        return queries;
    }
};

上面这段代码中最难想的地方在rest_h这个量,这个变量中记录的是裁剪掉当前节点为根的子树之后,剩余二叉树的深度。之所以要引入这个变量,是因为在向更深的子树前进时需要考虑到之前的情况,看如下这样的一种情况:

在这里插入图片描述
注意在求裁剪掉6号节点之后二叉树的高度时,它应该同时考虑到之前1-3-2构成的子树,但是这个子树的高度只有4号节点知道,在4号节点向更深的节点出发时,应该将之前子树的结果传递6号节点。6号节点在1-3-2和1-4-5-7构成的子树中找到更大值,这才是6号节点的结果值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
KMP算法是一种字符串匹配算法,用于在一个文本串S内查找一个模式串P的出现位置。它的时间复杂度为O(n+m),其中n为文本串的长度,m为模式串的长度。 KMP算法的核心思想是利用已知信息来避免不必要的字符比较。具体来说,它维护一个next数组,其中next[i]表示当第i个字符匹配失败时,下一次匹配应该从模式串的第next[i]个字符开始。 我们可以通过一个简单的例子来理解KMP算法的思想。假设文本串为S="ababababca",模式串为P="abababca",我们想要在S中查找P的出现位置。 首先,我们可以将P的每个前缀和后缀进行比较,得到next数组: | i | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | | --- | - | - | - | - | - | - | - | - | | P | a | b | a | b | a | b | c | a | | next| 0 | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 接下来,我们从S的第一个字符开始匹配P。当S的第七个字符和P的第七个字符匹配失败时,我们可以利用next[6]=4,将P向右移动4个字符,使得P的第五个字符与S的第七个字符对齐。此时,我们可以发现P的前五个字符和S的前五个字符已经匹配成功了。因此,我们可以继续从S的第六个字符开始匹配P。 当S的第十个字符和P的第八个字符匹配失败时,我们可以利用next[7]=1,将P向右移动一个字符,使得P的第一个字符和S的第十个字符对齐。此时,我们可以发现P的前一个字符和S的第十个字符已经匹配成功了。因此,我们可以继续从S的第十一个字符开始匹配P。 最终,我们可以发现P出现在S的第二个位置。 下面是KMP算法C++代码实现:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值