【力扣周赛】第 356 场周赛(数位DP)

chatgpt/2023/9/27 17:15:55

文章目录

  • Q1:6917. 满足目标工作时长的员工数目(简单枚举模拟题)
  • Q2:6900. 统计完全子数组的数目(双指针+滑动窗口)
  • Q3:6918. 包含三个字符串的最短字符串
  • Q4:6957. 统计范围内的步进数字数目(数位DP)
    • 补充:相似题目——P2657 [SCOI2009] windy 数
  • 成绩记录

Q1:6917. 满足目标工作时长的员工数目(简单枚举模拟题)

https://leetcode.cn/problems/number-of-employees-who-met-the-target/
在这里插入图片描述

按题意枚举遍历一遍即可。

class Solution {public int numberOfEmployeesWhoMetTarget(int[] hours, int target) {int ans = 0;for (int h: hours) {if (h >= target) ans++;}return ans;}
}

Q2:6900. 统计完全子数组的数目(双指针+滑动窗口)

https://leetcode.cn/problems/count-complete-subarrays-in-an-array/description/

在这里插入图片描述

数据范围比较小只有1000,使用 O ( n 2 ) O(n^2) O(n2) 的方法估计也能过,但是这里我使用了 O ( n ) O(n) O(n) 的双指针 + 滑动窗口。

使用双指针计算子数组数量的题目需要满足的性质,是以下两者之一:

  1. 当一个数组满足条件的情况下,增加一个元素必然仍满足条件。
  2. 当一个数组满足条件的情况下,去掉一个元素必然仍满足条件。

这里显然满足第一个性质。

枚举的是右端点,不断尝试将左端点向右移动。(在枚举的过程中,维护子数组中各个数字出现的频次,以及出现的不重复数字的个数,这里我是用哈希表来维护——哈希表的大小就是此时不重复数字的个数)。
对于每个右端点,当前左指针向左的所有位置都可以作为左端点,所以 ans += l + 1。

class Solution {public int countCompleteSubarrays(int[] nums) {// s.size()是整个数组种不同元素的数目Set<Integer> s = new HashSet<>();for (int num: nums) s.add(num);int n = nums.length, sum = s.size(), ans = 0;Map<Integer, Integer> m = new HashMap<>();      // 使用哈希表存储子数组中各个元素的数量for (int r = 0, l = 0; r < n; ++r) {m.merge(nums[r], 1, Integer::sum);while (m.get(nums[l]) > 1) {m.merge(nums[l], -1, Integer::sum);l++;}if (m.size() == sum) ans += l + 1;}return ans;}
}

Q3:6918. 包含三个字符串的最短字符串

https://leetcode.cn/problems/shortest-string-that-contains-three-strings/description/
在这里插入图片描述

这题感觉是挺怪的,但是数据范围比较小,字符串的长度只有 100 ,而且只有 3 个字符串。

只有 3 个字符串意味着只有 6 种拼接可能,分别是 abc,acb,bac,bca,cab,cba。(拼接的原则是找到最长的公共前后缀)
将这 6 个字符串放入列表中,按照 长度 + 字典序排序即可。

class Solution {public String minimumString(String a, String b, String c) {List<String> ls = new ArrayList<>();// 6种拼接顺序的可能ls.add(op(a, b, c));ls.add(op(a, c, b));ls.add(op(b, a, c));ls.add(op(b, c, a));ls.add(op(c, a, b));ls.add(op(c, b, a));// 按照长度和字典序排序Collections.sort(ls, (x, y) -> {int l1 = x.length(), l2 = y.length();return l1 != l2? l1 - l2: x.compareTo(y);});                   return ls.get(0);}// 按顺序拼接3个字符串public String op(String a, String b, String c) {String ans = op2(op2(a, b), c);return ans;}// 按顺序拼接2个字符串public String op2(String a, String b) {// 不断尝试尽可能少的使用字符串b中的字符for (int i = 0; i <= b.length(); ++i) {String t = a + b.substring(b.length() - i, b.length());// 如果拼接后包括b,说明找到了既包括a又包括b的字符串,直接返回if (t.indexOf(b) != -1) return t;   }// 程序不会走到这,因为上面枚举到最后时t = a+b 一定既包括a又包括b。return "";  }
}

对于代码块:

for (int i = 0; i <= b.length(); ++i) {String t = a + b.substring(b.length() - i, b.length());// 如果拼接后包括b,说明找到了既包括a又包括b的字符串,直接返回if (t.indexOf(b) != -1) return t;   
}

如果不理解的话可以看个例子——拼接 "aaa""abc"

"aaa" 在前,"abc" 在后。所以就是不断尝试 “aaa”,“aaac”,“aaabc” 中是否包括字符串 "abc"。(也就是不断尝试将字符串 "abc" 末尾的字符添加在字符串 "aaa" 之后)(因为我们是从少到多添加的,所以找到就返回,那么返回的一定是这种排列下最短的那个)

Q4:6957. 统计范围内的步进数字数目(数位DP)

在这里插入图片描述

经典的数位DP题目,相关的链接可见:
【算法】数位DP
【算法基础:动态规划】5.4 数位统计DP(计数问题)(数位DP)


数位DP 这种题目建议记下模板,对于不同的题目按照题目修改模板就好了。

dp数组的定义:memo[1][3] 表示 i = 0 填 3,从 i = 1 往后随便填的方案数。

class Solution {char[] s;int[][] memo;final int mod = (int)1e9 + 7;public int countSteppingNumbers(String low, String high) {int ans = op(high) - op(low);if (check(low)) ans++;		// 因为low可能是个很大的数字,不方便-1,所以单独判断return (ans + mod) % mod;   // +mod防止计算出负数}public int op(String n) {s = n.toCharArray();int m = s.length;memo = new int[m][10];for (int i = 0; i < m; ++i) Arrays.fill(memo[i], -1);   // -1表示没有被计算过return f(0, true, false, -1);}public int f(int i, boolean isLimit, boolean isNum, int last) {if (i == s.length) return isNum? 1: 0;if (!isLimit && isNum && memo[i][last] != -1) return memo[i][last];int res = 0;if (!isNum) res = f(i + 1, false, false, -1) % mod;int up = isLimit? s[i] - '0': 9;for (int d = isNum? 0: 1; d <= up; ++d) {if (Math.abs(d - last) == 1 || last == -1) {res = (res + f(i + 1, isLimit && d == up, true, d)) % mod;}}if (!isLimit && isNum) memo[i][last] = res;return res;}// 检查数字s 是否为 步进数public boolean check(String s) {for (int i = 1; i < s.length(); ++i) {if (Math.abs(s.charAt(i) - s.charAt(i - 1)) != 1) return false;}return true;}
}

做题的过程中一直卡样例

在这里插入图片描述
原因是 return (ans + mod) % mod; 写成了 return ans % mod;
具体来说,memo 数组里都是取模之后的数字,所以 op(high) 是可能比 op(low) 小的。

补充:相似题目——P2657 [SCOI2009] windy 数

https://www.luogu.com.cn/problem/P2657

在这里插入图片描述

跟这次周赛的题目几乎一模一样。

import java.util.*;public class Main {static long[][] memo;static char[] s;public static void main(String[] args) {Scanner scanner = new Scanner(System.in);int a = scanner.nextInt(), b = scanner.nextInt();System.out.println(op(b) - op(a - 1));}static long op(int a) {s = Integer.toString(a).toCharArray();int m = s.length;memo = new long[m][10];for (int i = 0; i < m; ++i) Arrays.fill(memo[i], -1);return f(0, true, false, -1);}static long f(int i, boolean isLimit, boolean isNum, int pre) {if (i == s.length) return isNum? 1: 0;if (!isLimit && isNum && memo[i][pre] != -1) return memo[i][pre];long res = 0;if (!isNum) res = f(i + 1, false, false, -1);int up = isLimit? s[i] - '0': 9;for (int d = isNum? 0: 1; d <= up; ++d) {if (pre == -1 || Math.abs(d - pre) >= 2) {res += f(i + 1, isLimit && d == up, true, d);}}if (!isLimit && isNum) memo[i][pre] = res;return res;}
}

在这里插入图片描述

成绩记录

在这里插入图片描述

在这里插入图片描述
T4 做慢了,少考虑了返回答案时需要先 + mod 再 % mod。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.exyb.cn/news/show-5312838.html

如若内容造成侵权/违法违规/事实不符,请联系郑州代理记账网进行投诉反馈,一经查实,立即删除!

相关文章

python错误提示:AttributeError: ‘DataFrame‘ object has no attribute ‘append‘

错误提示&#xff1a; AttributeError: ‘DataFrame’ object has no attribute ‘append’ 出现错误的代码&#xff1a; df_train_log pd.DataFrame() df_train_log df_train_log.append(log_train, ignore_indexTrue)原因&#xff1a; append包在pandas被弃用 解决方法&…

Python小红书旋转验证码识别

本周免费接了一个用户的需求&#xff0c;研究了一下小红书旋转验证码。刚开始小瞧了它&#xff0c;觉得它应该没有百度旋转验证码那么难&#xff0c;毕竟图像没有干扰&#xff0c;需要的训练样本就可以很少。然而事情并没有这么简单&#xff0c;所以记录一下。 首先看一下最终…

好用的备忘录app如何使用预设提醒功能?

备忘录的预设提醒功能是什么意思呢&#xff1f;就是在使用的过程中&#xff0c;提前预设好常用的提醒的时间&#xff0c;比如明天某个时间点、下周某个时间点等等&#xff0c;在需要设置提醒的时候&#xff0c;就可以直接使用。好用的备忘录app如何使用预设提醒功能&#xff1f…

AP5101 高压线性恒流电源驱动 输入 24-36V 输出3串18V LED线性恒流驱动方案

1,输入 24V-36V 输出3串18V 直亮 参考BOM 表如下 2,输入 24V-36V 输出3串18V 直亮 参考线路图 如下​ 3&#xff0c;产品描述 AP5101B 是一款高压线性 LED 恒流芯片&#xff0c;外围简单、内置功率管&#xff0c;适用于6- 60V 输入的高精度降压 LED 恒流驱动芯片。最大…

【云原生】一文学会Docker存储所有特性

目录 1.Volumes 1.Volumes使用场景 2.持久将资源存放 3. 只读挂载 2.Bind mount Bind mounts使用场景 3.tmpfs mounts使用场景 4.Bind mounts和Volumes行为上的差异 5.docker file将存储内置到镜像中 6.volumes管理 1.查看存储卷 2.删除存储卷 3.查看存储卷的详细信息…

MATLAB | 如何绘制这样的描边散点图?

part.-1 前前言 最近略忙可能更新的内容会比较简单&#xff0c;见谅哇&#xff0c;今日更新内容&#xff1a; part.0 前言 看到gzhBYtools科研笔记(推荐大家可以去瞅瞅&#xff0c;有很多有意思的图形的R语言复现&#xff01;&#xff01;)做了这样一张图&#xff1a; 感觉很…

【开发问题记录】01—大量数据同时插入数据库导致的时间戳重复问题

需求背景 用户登录之后将其云端收藏的内容同步到本地数据库且保持和原收藏顺序一致, 比如在电脑上登录之后显示的收藏顺序A->B->C 切换到手机登录之后的顺序预期也是A->B->C, 之后的查询就可以不依赖云端接口而是直接查本地数据库 代码抽象 针对这个场景我们抽象出…

python中有哪些异常,怎么处理

目录 python报的错误怎么处理 1. 使用 try-except 语句块 2. 使用 finally 语句块 3. 主动引发异常 python中有哪些异常 不知道是什么异常时怎么操作 总结 python报的错误怎么处理 在Python中&#xff0c;当程序执行时遇到错误&#xff0c;Python会抛出异常。要处理Pyt…
推荐文章