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

Leetcode - 双周赛155

目录

  • 一,3527. 找到最常见的回答
  • 二,3528. 单位转换 I
  • 三,3529. 统计水平子串和垂直子串重叠格子的数目
  • 四,3530. 有向无环图中合法拓扑排序的最大利润

一,3527. 找到最常见的回答

题目列表
在这里插入图片描述
本题是一道模拟题,对于 responses[i] 的每个元素,先使用 Set 进行去重,再枚举 Set,将其中的元素添加到 Map 中,最后统计出现次数最多的字符串,如果有多个,返回字典序最小的。

代码如下:

class Solution {public String findCommonResponse(List<List<String>> responses) {Map<String, Integer> map = new HashMap<>();String ans = "";int cnt = 0;for(List<String> res : responses){Set<String> set = new HashSet<>();// 去重for(String x : res){set.add(x);}// 统计出现次数 + 更新答案for(String x : set){map.merge(x, 1, Integer::sum);int c = map.get(x);if(c > cnt || c == cnt && x.compareTo(ans) < 0){cnt = c;ans = x;}}}return ans;}
}

二,3528. 单位转换 I

题目列表
在这里插入图片描述本题
本题提示,保证单位 0 可以通过唯一的转换路劲(不需要反向转换)转换成任何其他单位,说明它是一颗数,直接使用 dfs 遍历树来做。

代码如下:

class Solution {private static final int MOD = (int)1e9+7;public int[] baseUnitConversions(int[][] con) {int n = con.length + 1;int[] ans = new int[n];// 建树List<int[]>[] g = new ArrayList[n];Arrays.setAll(g, e->new ArrayList<>());for(int[] e : con){int x = e[0], y = e[1], w = e[2];g[x].add(new int[]{y, w});}ans[0] = 1;dfs(0, g, ans);return ans;}void dfs(int x, List<int[]>[] g, int[] ans){for(int[] e : g[x]){int y = e[0], w = e[1];// 防止溢出long res = (long) ans[x] * w % MOD;ans[y] = (int)res;dfs(y, g, ans);}}
}

三,3529. 统计水平子串和垂直子串重叠格子的数目

题目列表
在这里插入图片描述
本题求有多少个单元格它即使水平子串,又是垂直子串。字符串匹配问题直接想到 kmp 算法,剩下的就是如何判断随水平展开和垂直展开的字符串原来所在的位置:

  • 假设 n x m 的的矩阵
  • 对于水平展开的字符串 s1 来说,s1[i] = grid[i/m][i%m],其实 i = r1 * m + c1(r1,c1) = (i/m,i%m)
  • 对于垂直展开的字符串 s2 来说,s2[i] = grid[i/n][i%n],其实 i = r2 * n + c2(r2,c2) = (i/n,i%n)
  • 要是还不理解,自己画个图理一理就明白了,这里不多说了。

知道对应关系后,还有一个问题,就是通过 kmp 算法我们只能得知 [i-k+1,i] 是与 pattern 匹配的,k = pattern.length(),但是要怎么标记 [i-k+1,i] 这一段下标,如果暴力枚举标记会超时。其实可以发现,[i-k+1,i] 是一段区间,那么是否可以使用差分数组来解决,毕竟差分只用 O(1) 就能完成标记。答案是可以的,因为只需要判断前缀和是否大于 0 就可以判断它是否被标记且不会重复标记。

代码如下:

class Solution {public int countCells(char[][] grid, String pattern) {char[] p = pattern.toCharArray();int n = grid.length;int m = grid[0].length;int[] next = getNext(p);// 水平展开char[] g = new char[n * m];int k = 0;for(int i = 0; i < n; i++){for(int j = 0; j < m; j++){g[k++] = grid[i][j];}}int[] res1 = kmpSearch(g, p, next);// 垂直展开k = 0;for(int j = 0; j < m; j++){for(int i = 0; i < n; i++){g[k++] = grid[i][j];}}int[] res2 = kmpSearch(g, p, next);long s1 = 0;long s2 = 0;boolean[][] t = new boolean[n][m]; // 记录是否被标记for(int i = 0; i < n * m; i++){s1 += res1[i];if(s1 > 0) {int x = i / m;int y = i % m;t[x][y] = true;}}int ans = 0;for(int i = 0; i < n * m; i++){s2 += res2[i];if(s2 > 0) {int y = i / n;int x = i % n;if(t[x][y]) ans++;}}return ans;}// 求 next 数组private int[] getNext(char[] pattern) {int k = pattern.length;int[] next = new int[k];for(int i = 1, j = 0; i < k; i++){while(j > 0 && pattern[i] != pattern[j]){j = next[j-1];}if(pattern[i] == pattern[j])j++;next[i] = j;}return next;}// kmp 查询public int[] kmpSearch(char[] t, char[] pattern, int[] next) {int n = t.length;int[] res = new int[n + 1];// 差分数组int k = pattern.length;for(int i = 0, j = 0; i < n; i++){while(j > 0 && j < k && t[i] != pattern[j]){j = next[j-1];}if(t[i] == pattern[j]) {j++;}if(j == k){j = next[j-1];//[i-k+1 ,i]res[i-k+1]++;res[i+1]--;}}return res;}
}

四,3530. 有向无环图中合法拓扑排序的最大利润

题目列表
在这里插入图片描述
本题数据范围较小,可以使用状压来做,类似于全排列那道题,不过本题有个额外的要求,需要满足有效拓扑排序这一条件。简单解释一下拓扑排序——类似于做游戏任务,你要完成一个任务,但是必须要先完成它的前置任务才行,即它有一定的顺序,画个图理解一下:
在这里插入图片描述
这里为了方便计算,可以将它的前置任务也使用二进制来表示集合,代码如下:

class Solution {public int maxProfit(int n, int[][] edges, int[] score) {// 这个特判可以不加,但是速度会变慢if (edges.length == 0) {Arrays.sort(score);int ans = 0;for (int i = 0; i < n; i++) {ans += score[i] * (i + 1);}return ans;}// 使用二进制记录任务的前置任务int[] pre = new int[n];for(int[] e : edges){int x = e[0], y = e[1];pre[y] |= 1 << x;}memo = new int[1<<n];return dfs(0, pre, score);}int[] memo;// O(n*2^n)int dfs(int mask, int[] pre, int[] score){if(memo[mask] > 0) return memo[mask];int j = Integer.bitCount(mask) + 1;int res = 0;for(int i = 0; i < pre.length; i++) {// 判断是否已经做过该任务 + 判断前置任务是否做完if((mask >> i & 1) == 0 && (mask | pre[i]) == mask){res = Math.max(res, dfs(mask | (1 << i), pre, score) + j * score[i]);}}return memo[mask] = res;}
}

相关文章:

  • 超级好用的​​参数化3D CAD 建模​​图形库 (CadQuery库介绍)
  • 数字孪生的浪潮:从虚拟镜像到现实世界的 IT 变革
  • Rust 学习笔记:编程练习(一)
  • 计算机基础—(九道题)
  • 24体育NBA足球直播M28模板体育赛事直播源码
  • Rmarkdown输出为pdf的方法与问题解决
  • 从代码学习机器学习 - UMAP降维算法 scikit-learn版
  • Android 消息队列之MQTT的使用(二):会话+消息过期机制,设备远程控制,批量控制实现
  • JavaScript高级进阶(四)
  • Crusader Kings III 王国风云 3(十字军之王 3) [DLC 解锁] [Steam] [Windows SteamOS macOS]
  • Python(14)推导式
  • PCI/PXI 总线的可编程电阻卡
  • JVM模型、GC、OOM定位
  • leetcode 876. 链表的中间结点
  • 云上玩转DeepSeek系列之六:DeepSeek云端加速版发布,具备超高推理性能
  • SpringBoot实现接口防刷的5种高效方案详解
  • 安装qt4.8.7
  • cuDNN 安装、版本查看及指定版本删除操作指南
  • 社交电商和泛娱乐平台出海南美市场支付方式与策略
  • 人工智能搜索时代:如何优化SEO以保持领先
  • “自己生病却让别人吃药”——抹黑中国经济解决不了美国自身问题
  • 杜前任宁波中院代理院长,卸任宁波海事法院院长
  • 国家核准10台核电新机组,四大核电央企披露新项目进展
  • 国家能源局:支持民营企业参股投资核电项目
  • 借助AI应用,自闭症人群开始有可能真正“读懂他人”
  • 上海质子重离子医院已收治8000例患者,基本覆盖国内常见恶性肿瘤