当前位置: 首页 > news >正文

第 167 场双周赛 / 第 471 场周赛

第 167 场双周赛

Q1. 相等子字符串分数

给你一个由小写英文字母组成的字符串 s。

一个字符串的 得分 是其字符在字母表中的位置之和,其中 'a' = 1,'b' = 2,...,'z' = 26。

请你判断是否存在一个下标 i,使得该字符串可以被拆分成两个 非空子字符串 s[0..i] 和 s[(i + 1)..(n - 1)],且它们的得分 相等 。

如果存在这样的拆分,则返回 true,否则返回 false。

一个 子字符串 是字符串中 非空 的连续字符序列。

 

示例 1:

输入: s = "adcb"

输出: true

解释:

在下标 i = 1 处拆分:

左子字符串 = s[0..1] = "ad",得分 = 1 + 4 = 5
右子字符串 = s[2..3] = "cb",得分 = 3 + 2 = 5
两个子字符串的得分相等,因此输出为 true。

示例 2:

输入: s = "bace"

输出: false

解释:​​​​​​

没有拆分能产生相等的得分,因此输出为 false。

 

提示:

2 <= s.length <= 100
s 由小写英文字母组成。

解题思路:枚举分割点, 判断左半边和右半边是否相等

class Solution {
public:bool scoreBalance(string s) {int n=s.length();for(int i=0;i<n;i++){int sum_1=0,sum_2=0;for(int j=0;j<i+1;j++){sum_1+=(s[j]-'a'+1);}for(int k=i+1;k<n;k++){sum_2+=(s[k]-'a'+1);}if(sum_1==sum_2){return true;}}return false;}
};

Q2. 最长斐波那契子数组

给你一个由 正 整数组成的数组 nums。
斐波那契 数组是一个连续序列,其中第三项及其后的每一项都等于这一项前面两项之和。

返回 nums 中最长 斐波那契 子数组的长度。

注意: 长度为 1 或 2 的子数组总是 斐波那契 的。

子数组 是数组中 非空 的连续元素序列。

 

示例 1:

输入: nums = [1,1,1,1,2,3,5,1]

输出: 5

解释:

最长的斐波那契子数组是 nums[2..6] = [1, 1, 2, 3, 5]。

[1, 1, 2, 3, 5] 是斐波那契的,因为 1 + 1 = 2, 1 + 2 = 3, 且 2 + 3 = 5。

示例 2:

输入: nums = [5,2,7,9,16]

输出: 5

解释:

最长的斐波那契子数组是 nums[0..4] = [5, 2, 7, 9, 16]。

[5, 2, 7, 9, 16] 是斐波那契的,因为 5 + 2 = 7 ,2 + 7 = 9 且 7 + 9 = 16。

示例 3:

输入: nums = [1000000000,1000000000,1000000000]

输出: 2

解释:

最长的斐波那契子数组是 nums[1..2] = [1000000000, 1000000000]。

[1000000000, 1000000000] 是斐波那契的,因为它的长度为 2。

 

提示:

3 <= nums.length <= 10^5
1 <= nums[i] <= 10^9

解题思路:根据斐波那契数列的递推公式 an=an-1+an-2 (n>=2)

class Solution {
public:int longestSubarray(vector<int>& nums) {int n=nums.size(),cur_cnt=2,cnt=2;for(int i=2;i<n;i++){if(nums[i]-nums[i-1]==nums[i-2]){cur_cnt++; cnt=max(cur_cnt,cnt);}else{cur_cnt=2;}}return cnt;}
};

Q3. 设计考试分数记录器

Alice 经常参加考试,并希望跟踪她的分数以及计算特定时间段内的总分数。
请实现 ExamTracker 类:

ExamTracker(): 初始化 ExamTracker 对象。
void record(int time, int score): Alice 在时间 time 参加了一次新考试,获得了分数 score。
long long totalScore(int startTime, int endTime): 返回一个整数,表示 Alice 在 startTime 和 endTime(两者都包含)之间参加的所有考试的 总 分数。如果在指定时间间隔内 Alice 没有参加任何考试,则返回 0。
保证函数调用是按时间顺序进行的。即,

对 record() 的调用将按照 严格递增 的 time 进行。
Alice 永远不会查询需要未来信息的总分数。也就是说,如果最近一次 record() 调用中的 time = t,那么 totalScore() 总是满足 startTime <= endTime <= t 。
 

示例 1:

输入:
["ExamTracker", "record", "totalScore", "record", "totalScore", "totalScore", "totalScore", "totalScore"]
[[], [1, 98], [1, 1], [5, 99], [1, 3], [1, 5], [3, 4], [2, 5]]

输出:
[null, null, 98, null, 98, 197, 0, 99]

解释

ExamTracker examTracker = new ExamTracker();
examTracker.record(1, 98); // Alice 在时间 1 参加了一次新考试,获得了 98 分。
examTracker.totalScore(1, 1); // 在时间 1 和时间 1 之间,Alice 参加了 1 次考试,时间为 1,得分为 98。总分是 98。
examTracker.record(5, 99); // Alice 在时间 5 参加了一次新考试,获得了 99 分。
examTracker.totalScore(1, 3); // 在时间 1 和时间 3 之间,Alice 参加了 1 次考试,时间为 1,得分为 98。总分是 98。
examTracker.totalScore(1, 5); // 在时间 1 和时间 5 之间,Alice 参加了 2 次考试,时间分别为 1 和 5,得分分别为 98 和 99。总分是 98 + 99 = 197。
examTracker.totalScore(3, 4); // 在时间 3 和时间 4 之间,Alice 没有参加任何考试。因此,答案是 0。
examTracker.totalScore(2, 5); // 在时间 2 和时间 5 之间,Alice 参加了 1 次考试,时间为 5,得分为 99。总分是 99。
 

提示:

1 <= time <= 10^9
1 <= score <= 10^9
1 <= startTime <= endTime <= t,其中 t 是最近一次调用 record() 时的 time 值。
对 record() 的调用将以 严格递增 的 time 进行。
在 ExamTracker() 之后,第一个函数调用总是 record()。
对 record() 和 totalScore() 的总调用次数最多为 10^5 次。

解题思路:

【读完题就能想到前缀和+二分】,区别于普通数组的前缀和, 实现上要注意一点

using ll =long long;
class ExamTracker {
public:vector<ll> a,pre_sum={0};ExamTracker() {}void record(int time, int score) {a.push_back(time);pre_sum.push_back(pre_sum.back()+score);}long long totalScore(int startTime, int endTime) {int left=lower_bound(a.begin(),a.end(),startTime)-a.begin();int right=upper_bound(a.begin(),a.end(),endTime)-a.begin();return pre_sum[right]-pre_sum[left];}
};
/*** Your ExamTracker object will be instantiated and called as such:* ExamTracker* obj = new ExamTracker();* obj->record(time,score);* long long param_2 = obj->totalScore(startTime,endTime);*/

Q4. 最大划分因子

给你一个二维整数数组 points,其中 points[i] = [xi, yi] 表示笛卡尔平面上第 i 个点的坐标。
两个点 points[i] = [xi, yi] 和 points[j] = [xj, yj] 之间的 曼哈顿距离 是 |xi - xj| + |yi - yj|。

将这 n 个点分成 恰好两个非空 的组。一个划分的 划分因子 是位于同一组内的所有无序点对之间 最小 的曼哈顿距离。

返回所有有效划分中 最大 可能的 划分因子 。

注意: 大小为 1 的组不存在任何组内点对。当 n = 2 时(两个组大小都为 1),没有组内点对,划分因子为 0。

 

示例 1:

输入: points = [[0,0],[0,2],[2,0],[2,2]]

输出: 4

解释:

我们将点分成两组: {[0, 0], [2, 2]} 和 {[0, 2], [2, 0]}。

在第一组中,唯一的点对之间的曼哈顿距离是 |0 - 2| + |0 - 2| = 4。

在第二组中,唯一的点对之间的曼哈顿距离也是 |0 - 2| + |2 - 0| = 4。

此划分的划分因子是 min(4, 4) = 4,这是最大值。

示例 2:

输入: points = [[0,0],[0,1],[10,0]]

输出: 11

解释:

我们将点分成两组: {[0, 1], [10, 0]} 和 {[0, 0]}。

在第一组中,唯一的点对之间的曼哈顿距离是 |0 - 10| + |1 - 0| = 11。

第二组是单元素组,因此不存在任何点对。

此划分的划分因子是 11,这是最大值。

 

提示:

2 <= points.length <= 500
points[i] = [xi, yi]
-10^8 <= xi, yi <= 10^8

解题思路:

最大最小划分因子,貌似要用二分,如果答案是5,那么我们就不能将曼哈顿距离<5 的两个点形成的集合划分到同一个划分中,剩下的就类似于二分图的交替染色了【1,-1】

class Solution {
public:int n;vector<vector<int>> points;bool solve(int low){vector<int> a(n);auto dfs=[&](this auto&&dfs,int x,int c)->bool{a[x]=c;auto& p=points[x];for(int k=0;k<n;k++){auto& q=points[k];if(k==x || abs(p[0]-q[0])+abs(p[1]-q[1])>=low){continue;}if(a[k]==c || a[k]==0 && !dfs(k,-c)) return false;}return true;};for(int i=0;i<n;i++){if(a[i]==0 && !dfs(i,1)){return false;}}return true;}int maxPartitionFactor(vector<vector<int>>& points) {if(points.size()==2) return 0;this->n=points.size();this->points=points;int max_dis=0;for(int i=0;i<points.size();i++){for(int j=i+1;j<points.size();j++){max_dis=max(max_dis,abs(points[i][0]-points[j][0])+abs(points[i][1]-points[j][1]));}}int left=0,right=max_dis+1;while(left+1<right){int mid=left+(right-left)/2;if(solve(mid)) left=mid;else right=mid;}return left;}
};

第 471 场周赛

Q1. 出现次数能被 K 整除的元素总和

给你一个整数数组 nums 和一个整数 k。

请返回一个整数,表示 nums 中所有其 出现次数 能被 k 整除的元素的总和;如果没有这样的元素,则返回 0 。

注意: 若某个元素在数组中的总出现次数能被 k 整除,则它在求和中会被计算 恰好 与其出现次数相同的次数。

元素 x 的 出现次数 指它在数组中出现的次数。

 

示例 1:

输入: nums = [1,2,2,3,3,3,3,4], k = 2

输出: 16

解释:

数字 1 出现 1 次(奇数次)。
数字 2 出现 2 次(偶数次)。
数字 3 出现 4 次(偶数次)。
数字 4 出现 1 次(奇数次)。
因此总和为 2 + 2 + 3 + 3 + 3 + 3 = 16。

示例 2:

输入: nums = [1,2,3,4,5], k = 2

输出: 0

解释:

没有元素出现偶数次,因此总和为 0。

示例 3:

输入: nums = [4,4,4,1,2,3], k = 3

输出: 12

解释:

数字 1 出现 1 次。
数字 2 出现 1 次。
数字 3 出现 1 次。
数字 4 出现 3 次。
因此总和为 4 + 4 + 4 = 12。

 

提示:

1 <= nums.length <= 100
1 <= nums[i] <= 100
1 <= k <= 100

解题思路:

统计nums数组中各个元素出现的次数 能 被 k 整除的,答案加上【元素 * 出现次数】的总和

class Solution {
public:int sumDivisibleByK(vector<int>& nums, int k) {unordered_map<int,int> mp;int sum=0;for(auto& x: nums){mp[x]++;}for(auto& x: mp){if(x.second % k == 0) sum+=x.first*x.second;}return sum;}
};

Q2. 最长的平衡子串 I

给你一个由小写英文字母组成的字符串 s。
如果一个 子串 中所有 不同 字符出现的次数都 相同 ,则称该子串为 平衡 子串。

请返回 s 的 最长平衡子串 的 长度 。

子串 是字符串中连续的、非空 的字符序列。

 

示例 1:

输入: s = "abbac"

输出: 4

解释:

最长的平衡子串是 "abba",因为不同字符 'a' 和 'b' 都恰好出现了 2 次。

示例 2:

输入: s = "zzabccy"

输出: 4

解释:

最长的平衡子串是 "zabc",因为不同字符 'z'、'a'、'b' 和 'c' 都恰好出现了 1 次。

示例 3:

输入: s = "aba"

输出: 2

解释:

最长的平衡子串之一是 "ab",因为不同字符 'a' 和 'b' 都恰好出现了 1 次。另一个最长的平衡子串是 "ba"。

 

提示:

1 <= s.length <= 1000
s 仅由小写英文字母组成。

解题思路:1 <= s.length <= 1000,  看数据范围 n^2 能过,直接统计字符出现的次数,看子串是否平衡

class Solution {
public:int longestBalanced(string s) {int n = s.length();int max_len = 0;for (int i = 0; i < n; i++) {vector<int> freq(26, 0);int min_freq = INT_MAX;int max_freq = 0;for (int j = i; j < n; j++) {int idx = s[j] - 'a';freq[idx]++;min_freq = INT_MAX;max_freq = 0;for (int k = 0; k < 26; k++) {if (freq[k] > 0) {min_freq = min( min_freq, freq[k]);max_freq = max(max_freq, freq[k]);}}if (min_freq ==  max_freq) {max_len = max(max_len, j - i + 1);}}}return max_len;}
};

Q3. 最长的平衡子串 II

给你一个只包含字符 'a'、'b' 和 'c' 的字符串 s。
如果一个 子串 中所有 不同 字符出现的次数都 相同,则称该子串为 平衡 子串。

请返回 s 的 最长平衡子串 的 长度 。

子串 是字符串中连续的、非空 的字符序列。

 

示例 1:

输入: s = "abbac"

输出: 4

解释:

最长的平衡子串是 "abba",因为不同字符 'a' 和 'b' 都恰好出现了 2 次。

示例 2:

输入: s = "aabcc"

输出: 3

解释:

最长的平衡子串是 "abc",因为不同字符 'a'、'b' 和 'c' 都恰好出现了 1 次。

示例 3:

输入: s = "aba"

输出: 2

解释:

最长的平衡子串之一是 "ab",因为不同字符 'a' 和 'b' 都恰好出现了 1 次。另一个最长的平衡子串是 "ba"。

 

提示:

1 <= s.length <= 10^5
s 仅包含字符 'a'、'b' 和 'c'。

解题思路:

对比第二题,只有数据范围不同, 但是只有三种字符

分成如下三类问题,依次解答:

子串只包含一种字母。
子串只包含两种字母。

用分组循环分组,每组只包含两种字母。

对于每一组,计算含有相同数量的两种字母的最长子串

 

特殊的子串包含三种字母

设 a 在这个组的个数前缀和数组为 Sa​,b 在这个组的个数前缀和数组为 Sb,c 在这个组的个数前缀和数组为 Sc。

子串 [l,r) 中的字母 a,b,c 的出现次数相等,可以拆分为如下两个约束:

子串 [l,r) 中的字母 a 和 b 的出现次数相等。
子串 [l,r) 中的字母 b 和 c 的出现次数相等。
只要满足这两个约束,由等号的传递性可知,子串 [l,r) 中的字母 a 和 c 的出现次数相等,即三个字母的出现次数都相等。

两个约束即如下两个等式

Sa[r] - Sb[r] = Sa[l] - Sb[l]

Sb[r] - Sc[r] = Sb[l] - Sc[l]

定义数组 a[i] = (Sa[i]-Sb[i],Sb[i]-Sc[i])

问题变成:

计算数组 a 中的一对相等元素的最远距离。

    using ll=long long;
    class Solution {
    public:int longestBalanced(string s) {int n = s.size();int ans = 0;// 一种字母for (int i = 0; i < n;) {int start = i;for (i++; i < n && s[i] == s[i - 1]; i++);ans = max(ans, i - start);}// 两种字母two_char(s, 'a', 'b', ans);two_char(s, 'a', 'c', ans);two_char(s, 'b', 'c', ans);// 三种字母unordered_map<ll, int> pos = {{1LL * n << 32 | n, -1}};int cnt[3]{};for (int i = 0; i < n; i++) {cnt[s[i] - 'a']++;ll p = 1LL * (cnt[0] - cnt[1] + n) << 32 | (cnt[1] - cnt[2] + n);if (pos.contains(p)) {ans = max(ans, i - pos[p]);} else {pos[p] = i;}}return ans;}private:void two_char(const string& s, char x, char y, int& ans) {int n = s.size();for (int i = 0; i < n; i++) {unordered_map<int, int> pos = {{0, i - 1}}; int d = 0; for (; i < n && (s[i] == x || s[i] == y); i++) {d += s[i] == x ? 1 : -1;if (pos.contains(d)) {ans = max(ans, i - pos[d]);} else {pos[d] = i;}}}}
    };

    Q4. 完全平方数的祖先个数总和

    给你一个整数 n,以及一棵以节点 0 为根、包含 n 个节点(编号从 0 到 n - 1)的无向树。该树由一个长度为 n - 1 的二维数组 edges 表示,其中 edges[i] = [ui, vi] 表示在节点 ui 与节点 vi 之间有一条无向边。
    同时给你一个整数数组 nums,其中 nums[i] 是分配给节点 i 的正整数。

    定义值 ti 为:节点 i 的 祖先 节点中,满足乘积 nums[i] * nums[ancestor] 为 完全平方数 的祖先个数。

    请返回所有节点 i(范围为 [1, n - 1])的 ti 之和。

    说明:

    在有根树中,节点 i 的祖先是指从节点 i 到根节点 0 的路径上、不包括 i 本身的所有节点。
    完全平方数是可以表示为某个整数与其自身乘积的数,例如 1、4、9、16。

    解题思路:

    [8,2,4,4]

    求这个数组中有多少个数对的,它的乘积是一个完全平方数

    x*y=k^2

    将k^2分解成两个质因数的次方, 由于k^2的指数是偶数,因此x,y 被分解成某个质因数的次方时, 它们的指数是, 同奇/同偶的,然后我们对指数%2,得到的值,就是相等的

    x的平方剩余和 = y的平方剩余和

    eg : 12=2^2*3 -> 平方剩余部分 = 3

    本题就转换成祖先节点和后代节点,平方剩余和是否相等

    1 2 3 4 5 6 7 8 9 10

    平方剩余和 =1 【1,4,9...】

    平方剩余和 =2 【2,8....】8=2^2*2

    计算的是没有被标记过的数字, 从1,2,3.... 

    i*j^2<=mx, j<=sqrt(mx/i)

    using ll=long long;
    const int N = 1e5+10;
    vector<int> arr(N);
    class Solution {
    public:void solve(){for(int i=1;i<N;i++){if(arr[i]==0){for(int j=1;i*j*j<N;j++){arr[i*j*j]=i;}}}}long long sumOfAncestors(int n, vector<vector<int>>& edges, vector<int>& nums) {solve();vector<vector<int>> g(n);for(auto& x: edges){int a=x[0],b=x[1];g[a].push_back(b);g[b].push_back(a);}unordered_map<int,int> cnt;ll ans=0;auto dfs=[&](this auto&&dfs, int x,int fa)->void{int t=arr[nums[x]];ans+=cnt[t];cnt[t]++;for(int y:g[x]){if(y!=fa){dfs(y,x);}}cnt[t]--;  // 恢复初始状态};dfs(0,-1);return ans;}
    };

    感谢大家的点赞和关注,你们的支持是我创作的动力!

     

    http://www.dtcms.com/a/502928.html

    相关文章:

  • 聊聊 Unity(小白专享、C# 小程序 之 加密存储)
  • 如何推销网站分销商城开发多少钱
  • 大型的营销型网站建设做国外网站翻译中国小说赚钱
  • 论文学习_PalmTree: Learning an Assembly Language Model for Instruction Embedding
  • 基于PSO-BP粒子群优化神经网络+NSGAII多目标优化算法的工艺参数优化、工程设计优化(三个输出目标案例)!(Matlab源码和数据)
  • 端到端与世界模型(2):基于认知驱动的自动驾驶3.0
  • [嵌入式系统-143]:自动驾驶汽车与智能机器人的操作系统
  • Python设计模式 - 外观模式
  • [排序算法]希尔排序
  • 做网站应该用多少分辨率西安高端网站建设首选
  • FFmpeg 基本API avcodec_receive_frame函数内部调用流程分析
  • FFmpeg 基本API av_read_frame函数内部调用流程分析
  • 广东网站建设包括什么口碑好网站建设是哪家
  • 和田地区建设局网站电子商务网络营销是干嘛的
  • SAP B1实施专家指南:如何优化成本与缩短项目周期?
  • [吾爱大神原创工具] Python多功能自动化点击录入工具V1.0
  • 不备案怎么做淘宝客网站wordpress 字体调整
  • 栈及相关算法问题
  • Docker镜像分层与写时复制原理详解
  • 药物靶点研究3天入门|Day1:从疾病差异里挖“潜力靶点”,两步锁定真目标
  • WebForms ArrayList详解
  • 达梦数据库性能调优总结
  • [JavaEE初阶]HTTPS-SSL传输过程中的加密
  • 单片机开发中裸机系统有哪些(轮询、时间片、前后台.....)
  • 一次线上MySQL分页事故,搞了半夜...
  • 医院网站建设思路深圳展览设计公司
  • C#WPF关键类
  • 从文件加密到数据料理台:两款主流加密工具(EncFSMP/CyberChef)技术特性解析与开发实战选型
  • 什么是uv和传统的区别
  • FastAPI之 处理HTTP请求