当前位置:   article > 正文

Leetcode - 周赛399

Leetcode - 周赛399

目录

一,3162. 优质数对的总数 I

二,3163. 压缩字符串 III

三,3164. 优质数对的总数 II

四, 3165. 不包含相邻元素的子序列的最大和


一,3162. 优质数对的总数 I

假设 x 是 nums1 数组中的值,y 是 nums2 数组中值,我们要求的就是有几个 (x,y) 满足

x % (y * k) == 0,可以直接暴力 

代码如下:

  1. class Solution {
  2. public int numberOfPairs(int[] nums1, int[] nums2, int k) {
  3. int ans = 0;
  4. for(int x : nums1){
  5. for(int y : nums2){
  6. if(x%(y*k)==0) ans++;
  7. }
  8. }
  9. return ans;
  10. }
  11. }

二,3163. 压缩字符串 III

本题是一道模拟题,遍历word字符串,将相邻且字符相同的子字符串,写成数字+字符的形式,比如 "aaabbc",写成 "3a2b1c",注意,数字最大是9,也就是说如果遇到比如12个连续的'a',我们要写成 "9a3a"。

代码如下: 

  1. class Solution {
  2. public String compressedString(String word) {
  3. int cnt = 1;
  4. char[] ch = word.toCharArray();
  5. StringBuilder res = new StringBuilder();
  6. for(int i=1; i<ch.length; i++){
  7. if(ch[i] == ch[i-1] && cnt < 9){
  8. cnt++;
  9. }else{
  10. res.append(cnt);
  11. res.append(ch[i-1]);
  12. cnt = 1;
  13. }
  14. }
  15. if(cnt > 0){
  16. res.append(cnt);
  17. res.append(ch[ch.length-1]);
  18. }
  19. return res.toString();
  20. }
  21. }

三,3164. 优质数对的总数 II

1. 预处理被除数:

  • 要求满足 x % (y * k) == 0 的数对(x,y),可以先枚举nums1数组,使用哈希表统计出 x / k 的所有因子及其对应的数量,再枚举 nums2 数组,看 y 是否是x/k的因子(即是否在哈希表中),如果存在,加上对应的值。最终得出答案

2.预处理除数

  • 除了上述做法,我们还可以先枚举nums1数组,使用哈希表统计出 x / k 及其对应的数量,枚举nums2数组,枚举 y 的倍数及其数量,看是否在哈希表中,如果存在,加上对应的值。最终得出答案

代码如下:

  1. class Solution {
  2. //预处理被除数x
  3. public long numberOfPairs(int[] nums1, int[] nums2, int k) {
  4. Map<Integer, Integer> map = new HashMap<>();
  5. for(int x : nums1){//统计 <x/k 的因子, 对应的数量>
  6. if(x%k == 0){
  7. for(int i=1; i<=Math.sqrt(x/k); i++){
  8. if(x/k%i == 0){
  9. map.merge(i, 1, Integer::sum);
  10. if(i < x/k/i)
  11. map.merge(x/k/i, 1, Integer::sum);
  12. }
  13. }
  14. }
  15. }
  16. long ans = 0;
  17. for(int y : nums2){
  18. ans += map.getOrDefault(y, 0);
  19. }
  20. return ans;
  21. }
  22. }
  23. class Solution {
  24. //预处理除数y
  25. public long numberOfPairs(int[] nums1, int[] nums2, int k) {
  26. //O(n+m+(mx/k)logm)
  27. Map<Integer, Integer> map1 = new HashMap<>();
  28. long mx = 0;
  29. for(int x : nums1){//统计 <x/k,x/k的数量>
  30. if(x%k == 0){
  31. map1.merge(x/k, 1, Integer::sum);
  32. mx = Math.max(mx, x/k);
  33. }
  34. }
  35. Map<Integer, Integer> map2 = new HashMap<>();
  36. for(int y : nums2){
  37. map2.merge(y, 1, Integer::sum);
  38. }
  39. long ans = 0;
  40. for(int y : map2.keySet()){
  41. int s = 0;
  42. for(int j=y; j<=mx; j+=y){//枚举 y 的倍数
  43. s += map1.getOrDefault(j, 0);
  44. }
  45. ans += (long) s * map2.get(y);
  46. }
  47. return ans;
  48. }
  49. }

四, 3165. 不包含相邻元素的子序列的最大和

本题一看就是一道标准的打家劫舍问题,直接上代码:

  1. class Solution {
  2. public int maximumSumSubsequence(int[] nums, int[][] queries) {
  3. int MOD = (int)1e9 + 7;
  4. int n = nums.length;
  5. int[] f = new int[n];
  6. int ans = 0;
  7. for(int[] q : queries){
  8. nums[q[0]] = q[1];
  9. f[0] = Math.max(0, nums[0]);
  10. for(int i=1; i<n; i++){
  11. f[i] = Math.max(f[i-1], (i>1?f[i-2]:0)+nums[i]);
  12. }
  13. System.out.println(f[n-1]);
  14. ans = (ans+f[n-1])%MOD;
  15. }
  16. return ans;
  17. }
  18. }

但是上述做法会超时,需要换一种做法,这题实际上需要使用线段树动态维护[0,n-1]的最大值,就是将 [l,r] = [l,mid] + [mid+1,r],不断的分治,但是由于题目要求不包含相邻元素,也就是说mid 和 mid+1这两个点最多只能取一个,而只靠一维数组无法维护,所以需要一个二维数组f[n][4],这里先用f00,f01,f10,f11表示一下它们的状态:

  • f00:表示[l,r]l,r都不选的合法最大值
  • f01:表示[l,r]l不选的合法最大值(r可选可不选)
  • f10:表示[l,r]r不选的合法最大值(l可选可不选)
  • f11:表示[l,r]都可以选的合法最大值(l,r可选可不选)

它们之间的递推关系:

  • f00 = max(f01+f00, f00+f10)
  • f01 = max(f00+f11, f01+f01)
  • f10 = max(f10+f10, f11+f00)
  • f11 = max(f10+f11, f11+f01)

画个图来理解一下:

剩下的基本都是线段树基本方法,没什么变化,代码如下:

  1. class Solution {
  2. //f00:表示[l,r]l,r都不选的合法最大值
  3. //f01:表示[l,r]l不选的合法最大值(r可选可不选)
  4. //f10:表示[l,r]r不选的合法最大值(l可选可不选)
  5. //f11:表示[l,r]都可以选的合法最大值(l,r可选可不选)
  6. //[l, r] = [l, mid] + [mid+1, r]
  7. // 00 01 10 11
  8. //f00 = max(f01+f00, f00+f10)
  9. //f01 = max(f00+f11, f01+f01)
  10. //f10 = max(f10+f10, f11+f00)
  11. //f11 = max(f10+f11, f11+f01)
  12. int[][] f;
  13. int[] a;
  14. void maintain(int i){
  15. f[i][0] = Math.max(f[i<<1][1]+f[i<<1|1][0], f[i<<1][0]+f[i<<1|1][2]);
  16. f[i][1] = Math.max(f[i<<1][0]+f[i<<1|1][3], f[i<<1][1]+f[i<<1|1][1]);
  17. f[i][2] = Math.max(f[i<<1][2]+f[i<<1|1][2], f[i<<1][3]+f[i<<1|1][0]);
  18. f[i][3] = Math.max(f[i<<1][2]+f[i<<1|1][3], f[i<<1][3]+f[i<<1|1][1]);
  19. }
  20. void build(int l, int r, int i){
  21. if(l == r){
  22. f[i][3] = Math.max(0, a[l]);
  23. }else{
  24. int mid = (l + r) / 2;
  25. build(l, mid, i<<1);
  26. build(mid+1, r, i<<1|1);
  27. maintain(i);
  28. }
  29. }
  30. void update(int l, int r, int i, int R, int val){
  31. if(l == r){
  32. f[i][3] = Math.max(0, val);
  33. return;
  34. }
  35. int mid = (l + r) / 2;
  36. if(R <= mid){
  37. update(l, mid, i<<1, R, val);
  38. }else{
  39. update(mid+1, r, i<<1|1, R, val);
  40. }
  41. maintain(i);
  42. }
  43. int query(int l, int r, int i){
  44. return f[i][3];
  45. }
  46. public int maximumSumSubsequence(int[] nums, int[][] queries) {
  47. int MOD = (int)1e9 + 7;
  48. int n = nums.length;
  49. f = new int[n<<2][4];
  50. a = nums;
  51. build(0, n-1, 1);
  52. int ans = 0;
  53. for(int[] q : queries){
  54. update(0, n-1, 1, q[0], q[1]);
  55. ans = (ans + query(0, n-1, 1))%MOD;
  56. }
  57. return ans%MOD;
  58. }
  59. }
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/正经夜光杯/article/detail/859584
推荐阅读
相关标签
  

闽ICP备14008679号