第281场周赛
链接↓
第281场周赛
小tips:由于国内服务器502崩溃,因此该周赛时长加长了10分钟
2180.统计各位数字之和为偶数的整数个数 给你一个正整数 num
,请你统计并返回 小于或等于 num
且各位数字之和为 偶数 的正整数的数目。
正整数的 各位数字之和 是其所有位上的对应数字相加的结果。
示例 1:
1 2 3 4 输入:num = 4 输出:2 解释: 只有 2 和 4 满足小于等于 4 且各位数字之和为偶数。
示例 2:
1 2 3 4 5 输入:num = 30 输出:14 解释: 只有 14 个整数满足小于等于 30 且各位数字之和为偶数,分别是: 2、4、6、8、11、13、15、17、19、20、22、24、26 和 28 。
提示:
小彩蛋:本题在比赛过程中示例二的解释出现了严重错误,只有 14 个整数满足小于等于 30中的30误打成了4
分析:
暴力枚举,按题目意思来
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 class Solution {public : int countEven (int num) { int ans=0 ; for (int i=1 ;i<=num;i++){ int a=i/10 %10 ; int b=i/100 %100 ; int c=i/1000 %1000 ; if ((i+a+b+c)%2 ==0 ){ ans++; } } return ans; } };
2181.合并零之间的节点 给你一个链表的头节点 head
,该链表包含由 0
分隔开的一连串整数。链表的 开端 和 末尾 的节点都满足 Node.val == 0
。
对于每两个相邻的 0
,请你将它们之间的所有节点合并成一个节点,其值是所有已合并节点的值之和。然后将所有 0
移除,修改后的链表不应该含有任何 0
。
返回修改后链表的头节点 head
。
示例 1:
1 2 3 4 5 6 输入:head = [0,3,1,0,4,5,2,0] 输出:[4,11] 解释: 上图表示输入的链表。修改后的链表包含: - 标记为绿色的节点之和:3 + 1 = 4 - 标记为红色的节点之和:4 + 5 + 2 = 11
示例 2:
1 2 3 4 5 6 7 输入:head = [0,1,0,3,0,2,2,0] 输出:[1,3,4] 解释: 上图表示输入的链表。修改后的链表包含: - 标记为绿色的节点之和:1 = 1 - 标记为红色的节点之和:3 = 3 - 标记为黄色的节点之和:2 + 2 = 4
提示:
列表中的节点数目在范围 [3, 2 * 105]
内
0 <= Node.val <= 1000
不 存在连续两个 Node.val == 0
的节点
链表的 开端 和 末尾 节点都满足 Node.val == 0
分析:
遍历一次链表,设立一个容器,从第一个0到下一个为0中间的数求和,若中间没有数直接过,结点即都在num内。
记ret为头指针,cur为尾指针,通过循环vector的数字,让尾指针指向新节点并且把尾指针移过去。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 class Solution {public : ListNode* mergeNodes (ListNode* head) { head=head->next; int sum=0 ; vector<int > num; while (head!=NULL ){ if (head->val==0 ){ num.push_back (sum); sum=0 ; } else { sum+=head->val; } head=head->next; } ListNode *ret,*cur; ret=cur=new ListNode (num[0 ]); int m=num.size (); for (int i=1 ;i<m;i++){ ListNode *node = new ListNode (num[i]); cur->next=node; cur=cur->next; } return ret; } };
2182.构造限制重复的字符串 给你一个字符串 s
和一个整数 repeatLimit
,用 s
中的字符构造一个新字符串 repeatLimitedString
,使任何字母 连续 出现的次数都不超过 repeatLimit
次。你不必使用 s
中的全部字符。
返回 字典序最大的 repeatLimitedString
。
如果在字符串 a
和 b
不同的第一个位置,字符串 a
中的字母在字母表中出现时间比字符串 b
对应的字母晚,则认为字符串 a
比字符串 b
字典序更大 。如果字符串中前 min(a.length, b.length)
个字符都相同,那么较长的字符串字典序更大。
示例 1:
1 2 3 4 5 6 7 8 9 输入:s = "cczazcc", repeatLimit = 3 输出:"zzcccac" 解释:使用 s 中的所有字符来构造 repeatLimitedString "zzcccac"。 字母 'a' 连续出现至多 1 次。 字母 'c' 连续出现至多 3 次。 字母 'z' 连续出现至多 2 次。 因此,没有字母连续出现超过 repeatLimit 次,字符串是一个有效的 repeatLimitedString 。 该字符串是字典序最大的 repeatLimitedString ,所以返回 "zzcccac" 。 注意,尽管 "zzcccca" 字典序更大,但字母 'c' 连续出现超过 3 次,所以它不是一个有效的 repeatLimitedString 。
示例 2:
1 2 3 4 5 6 7 8 9 输入:s = "aababab", repeatLimit = 2 输出:"bbabaa" 解释: 使用 s 中的一些字符来构造 repeatLimitedString "bbabaa"。 字母 'a' 连续出现至多 2 次。 字母 'b' 连续出现至多 2 次。 因此,没有字母连续出现超过 repeatLimit 次,字符串是一个有效的 repeatLimitedString 。 该字符串是字典序最大的 repeatLimitedString ,所以返回 "bbabaa" 。 注意,尽管 "bbabaaa" 字典序更大,但字母 'a' 连续出现超过 2 次,所以它不是一个有效的 repeatLimitedString 。
提示:
1 <= repeatLimit <= s.length <= 105
s
由小写英文字母组成
分析:
对于本题我们遍历一遍s,记录一下每个字母出现的次数,设立一个答案和当前值last描述的是哪个字母。
通过从后往前遍历,字典序大的优先输出,如果c和当前输入的是同一个值,那么我们判断是否超过repeatLimit,写入ans,记录一次reps,cnt内的字母数量减掉一个;如果c和当前输入的不是一个值,那么我们写进ans,记录一下这个值,记录一次reps,cnt内的字母数量减掉一个,如果最后遍历完仍然没有字母,那么我们直接跳出循环即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 int cnt[30 ];class Solution {public : string repeatLimitedString (string s, int repeatLimit) { memset (cnt,0 ,sizeof (cnt)); for (char c:s) cnt[c-'a' ]+=1 ; string ans="" ; char last='#' ; int reps=0 ; while (true ){ bool flag=false ; for (int i=25 ;i>=0 && !flag;i--){ if (cnt[i]==0 ) continue ; char c=(char )(i+'a' ); if (c==last){ if (reps+1 <=repeatLimit){ ans+=c; reps+=1 ; flag=true ; cnt[i]-=1 ; } }else { ans+=c; last=c; reps=1 ; flag=true ; cnt[i]-=1 ; } } if (!flag) break ; } return ans; } };
2183.统计可以被 K 整除的下标对数目 给你一个下标从 0 开始、长度为 n
的整数数组 nums
和一个整数 k
,返回满足下述条件的下标对 (i, j)
的数目:
0 <= i < j <= n - 1
且
nums[i] * nums[j]
能被 k
整除。
示例 1:
1 2 3 4 5 6 7 输入:nums = [1,2,3,4,5], k = 2 输出:7 解释: 共有 7 对下标的对应积可以被 2 整除: (0, 1)、(0, 3)、(1, 2)、(1, 3)、(1, 4)、(2, 3) 和 (3, 4) 它们的积分别是 2、4、6、8、10、12 和 20 。 其他下标对,例如 (0, 2) 和 (2, 4) 的乘积分别是 3 和 15 ,都无法被 2 整除。
示例 2:
1 2 3 输入:nums = [1,2,3,4], k = 5 输出:0 解释:不存在对应积可以被 5 整除的下标对。
提示:
1 <= nums.length <= 105
1 <= nums[i], k <= 105
分析:
首先本题与第72场双周赛的第一题是一个题目,不同的是本题卡了时间复杂度,因此如果考虑暴力的话会有这个错误
↓↓↓
Line 7: Char 24: runtime error: signed integer overflow: 98382 * 23997 cannot be represented in type ‘int’ (solution.cpp) SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior prog_joined.cpp:16:24
首先我们用cnts记录一下数组中每个数字出现多少次,再用rcnts记录当前这个i和我们目标数字乘起来是k的倍数。
后面我们就可以统计答案了,对于每一种值来遍历,对下标i,去找另一个下表至少需要拥有什么样的因子,能使得被k整除,即为nv,ans加上
cnts[i]*rcnts[nv](乘积为k的倍数),最后除去自己乘自己的情况,即(i==j),我们剩下了(i>j)与(i<j)的情况,由于题目要求i<j,那么我们只需要对ans除2即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #define LL long long int Gcd (int a,int b) { if (b==0 ) return a; return Gcd (b,a%b); } const int MAXN=1e5 +55 ;LL cnts[MAXN]; LL rcnts[MAXN]; class Solution {public : long long countPairs (vector<int >& nums, int k) { int n=nums.size (),mx=0 ; memset (cnts,0 ,sizeof (cnts)); for (int i=0 ;i<n;i++) nums[i]=Gcd (nums[i],k); for (int i=0 ;i<n;i++) cnts[nums[i]]+=1 ,mx=max (mx,nums[i]); memset (rcnts,0 ,sizeof (rcnts)); for (int i=1 ;i<=mx;i++) for (int j=i;j<=mx;j+=i) rcnts[i]+=cnts[j]; LL ans=0 ; for (int i=0 ;i<=mx;i++){ if (cnts[i]==0 ) continue ; int nv=k/Gcd (k,i); ans=ans+cnts[i]*rcnts[nv]; if (1LL *i*i%k==0 ) ans-=cnts[i]; } return ans/2LL ; } };