力扣 LeetCode-CN 第30场双周赛

最终成绩:

471 / 2545 zclhit 18 1:22:33 0:09:06 1 0:18:59 0:33:57 1 1:02:33 2

起因

最近一个多月自己有在坚持刷leetcode的每日一题,这次终于鼓起勇气参加了一场双周赛,用大佬的话说这场比赛就是手速赛,所以4道题都AK的人数很多。无聊刷起讨论区看到各位大佬都在讨论,想把第一次参赛的经历记录下来,因为Leetcode周赛和双周赛题目都比较新,所以能混个热搜什么的也挺好的嘤嘤嘤。

正文

5177. 转变日期格式 - E

题目内容: :https://leetcode-cn.com/problems/reformat-date/
思路:
典型的手速题,日期时间转换,很多cpp大佬在这道题上纷纷投向了js的怀抱。
解题代码:

public static String reformatDate(String date) {
    String[] s = date.split(" ");
    int day = processDay(s[0]);
    Map<String, Integer> monthMap = new HashMap<>();
    monthMap.put("Jan", 1);
    monthMap.put("Feb", 2);
    monthMap.put("Mar", 3);
    monthMap.put("Apr", 4);
    monthMap.put("May", 5);
    monthMap.put("Jun", 6);
    monthMap.put("Jul", 7);
    monthMap.put("Aug", 8);
    monthMap.put("Sep", 9);
    monthMap.put("Oct", 10);
    monthMap.put("Nov", 11);
    monthMap.put("Dec", 12);
    int month = monthMap.get(s[1]);
    String ms = fillZero(month);
    int year = Integer.parseInt(s[2]);
    String ds = fillZero(day);
    return year + "-" + ms + "-" + ds;
  }

  private static String fillZero(int month) {
    if(month<10) {
      return "0" + month;
    }
    return String.valueOf(month);
  }

  private static int processDay(String s) {
    if (s.length() == 3) {
      return Integer.parseInt(s.substring(0, 1));
    } else {
      return Integer.parseInt(s.substring(0, 2));
    }
  }

5445. 子数组和排序后的区间和 - M

题目内容: :https://leetcode-cn.com/problems/range-sum-of-sorted-subarray-sums/
思路:
我直接用暴力枚举+排序做出来的,没有超时但是也忘记了取模,后面有空会认真看一下其他大神的思路,毕竟刷题数量不是目的,掌握了优秀的思路才能更进一步。
解题代码:

public int rangeSum(int[] nums, int n, int left, int right) {
    int[] arr = new int[(n * (n + 1) / 2)];
    int idx = 0;
    for (int i = 0; i < n; i++) {
      for (int j = i; j < n; j++) {
        arr[idx] = sum(nums, i, j);
        idx++;
      }
    }
    Arrays.sort(arr);
    return sum(arr, left-1, right-1);
  }

  private int sum(int[] nums, int start, int end) {
    int res = 0;
    for(int i=start; i<=end; i++) {
      res += nums[i];
    }
    return res;
  }

5446.三次操作后最大值与最小值的最小差 - M

题目内容: :https://leetcode-cn.com/problems/minimum-difference-between-largest-and-smallest-value-in-three-moves/
思路:
这道题思路比较好想,需要变化后差值最小,那么一定是要么把最大的值调整,要么是把最小的值调整,每次操作都操作一个最大值或最小值,很容易的我们想到需要先排序。至于每次操作的是最大值,还是最小值,其实取决于数组中其他数的分布情况,这里因为只需要操作三次,所以我们可以遍历各种情况,比如变动三个最小值,变动两个最小值一个最大值,变动一个最小值两个最大值,变动三个最大值。取其中最优化的结果即可。(我的代码后面的循环可以优化,进而拓展到N次操作的最大值最小值差值问题)
解题代码:

if (nums.length <= 4) {
      return 0;
    }
    Arrays.sort(nums);
    int a1 = nums[nums.length - 4] - nums[0];
    int a2 = nums[nums.length - 3] - nums[1];
    int a3 = nums[nums.length - 2] - nums[2];
    int a4 = nums[nums.length - 1] - nums[3];
    return Math.min(Math.min(a1, a2), Math.min(a3, a4));

5447. 石子游戏 IV - H

题目内容: :https://leetcode-cn.com/problems/stone-game-iv/
思路:
这道题可以说是非常有意思了,明显的可以用到递归或者动态规划或者记忆数组(i dont know how to call it)的思想,从只有一个石头开始,到两个石头,可以在纸上画一下前几次的结果分别是:
i=1 is true
i=2 is false
i=3 is true
i=4 is true
i=5 is false
i=6 is true
i=7 is false
i=8 is true
i=9 is true
i=10 is false
i=11 is true
i=12 is false
i=13 is true
i=14 is true
i=15 is false
i=16 is true
i=17 is false
那么我么来根据题目内容思考一下规律,以i = 17为例,Alice第一次可以拿走1, 4, 9, 16个石子,那么在拿走这些石子之后分别剩下:16, 13, 8, 1个石子,而根据计算我们已经知道了前16个石子的胜败情况,分别都是true,也就是说不管Alice怎么样拿石子,留给Bob的一定是获胜的石子,怎么样,计算i = 17的时候实际上是运用了i= 1, 8, 13, 16的结果,那么对1, 8 ,13, 16的计算也一定取决于更小的石子选择的结果。所以我们可以从1开始,只有1个石子,Alice获胜,很好,数组第一个元素已经初始化了,有2个石子,Alice只能拿1个,剩下1个给Bob,而查找之前的数组,dp[1]= true,所以Bob必胜。那么我们看i = 11的情况,i = 13的时候,Alice可以拿1, 4, 9个石子,分别留下12, 9, 4个石子给Bob,获胜情况是false, true, true,那么Alice可以选择只拿1个石子让Bob失败。也就是说,如果当前数字i是整数的平方数,那么Alice一次全拿走,必胜,否则查看Alice拿走所有平方数可能的结果,如果存在一次让Bob为false的结果,Alice就能获胜。接下来看代码:
解题代码:

public boolean winnerSquareGame(int n) {
    boolean[] dp = new boolean[n+1];
    for(int i=1; i<=n; i++) {
      if(isPower(i)) {
        dp[i] = true;
        continue;
      }
      dp[i] = process(dp, i);
    }
    return dp[n];
  }

  private boolean process(boolean[] dp, int target) {
    boolean res = true;
    for(int i=1; i<=Math.sqrt(target)+1; i++) { // 遍历所有拿走石子的可能
      if(target - i*i >0) {
        res = res && dp[target - i*i]; // 只要有一次为false, Alice就能获胜
      }
    }
    return !res;
  }

  private boolean isPower(int i) { // 判断是否是平方数
    for(int a =1; a<Math.sqrt(i)+1; a++) {
      if(a*a == i) {
        return true;
      }
    }
    return false;
  }```

你可能感兴趣的:(LeetCode)