「第 329 场周赛」复盘:又被自己蠢哭了,或许我是刷题走火入魔了,需要休息了……
2635
2023.01.22
发布于 未知归属地

[toc]
小海报日常镇楼

第 329 场周赛

估计要掉很多分,麻了,自抱自泣中。只做出了 T1、T2,T3 功败垂成,叹气……

排名 1344 / 2591。

T1、T2:手速真的太慢,绝望

3 分 - 交替数字和
4 分 - 根据第 K 场考试的分数排序

不知道大佬们都是怎么样在几十秒内秒杀的,实名羡慕。我反正是做的很慢,光第一题就用了10分钟。

难道大佬们都不读题吗?虽然说这两题很简单吧,但我感觉我光理解题意,每道也要耗费至少3分钟,然后尝试执行检查错误,又要花至少 3 分钟。人和人的差距好大😭。

我觉得这一点上我无论怎么练习,也很难提高了,这个受限于我大脑神经网络的效率,天生慢,真的忧伤…… 求安慰,求支招😭

T3:分明月在梅枝上,寻到梅边月又无

5 分 - 执行逐位运算使字符串相等

这道题本来很有希望,真的就差一点点就成功了,值得好好反思一下。

一开始我尝试分类讨论:让 s 和 target 第 i 位的数字组成二进制 01、10、11、00,考察怎样才能把 01 变成 11,把 10 变成 00。

但是自己和自己讨论,讨论着、讨论着就把自己搞晕了,以至于反复检查自己是不是算错了:
image.png

上图中的注释就是头脑风暴的过程,这个注释被反复检查修改了 N 遍,到了第 N 遍时,我已经感觉天玄地黄,宇宙洪荒了,彻底把自己绕晕了。

然后尝试着强迫迫自己冷静下来,确定思路:

  1. 统计01、10、11、00 出现的次数
  2. 如果 01 的数量大于 10 和 11 的总和,则 01 无法被全部转换。
  3. 处理完 01,接着处理 10。10 总是可以反复和自己相作用,转换成 00,所以不管有多少个 10,最后都会只剩下一个。
  4. 剩下的那个 10,只能和 11 相互作用,把自己转换成 00,并维持 11 不变。所以至少 1 个 11,就能将 01 都干掉。

事后看,这个思路是没问题,但是我编码时,内心很慌张,而且不断怀疑自己。当时只剩 15 分钟了,比赛结束后,我调试了好几次才搞定:

调通的代码

class Solution {
    public boolean makeStringsEqual(String s, String target) {
        int n = s.length();
        int[] cnt = new int[4];
        for(int i = 0; i < n; i++){
            int k = helper(s.charAt(i), target.charAt(i));
            cnt[k]++;
        }
        while(cnt[1] > 0 && cnt[2] + cnt[3] > 0){
            int count = Math.min(cnt[1], cnt[2] + cnt[3]);
            cnt[1] -= count;
            cnt[3] += count;
        }
        if(cnt[1] > 0)return false;
  
        if(cnt[2] > 0){
            // cnt[2] = 1;
            if(cnt[3] < 1)return false;
        }
        return true;
    }
  
    private int helper (char c1, char c2){
        return (c1 - '0') * 2 + (c2 - '0');
    }
}

优化一下

前面的代码虽然调试通了,但是 while 循环里做了无用的工作。仔细想想就会意识到:只要有一个 10 或者 11,就能像核聚变一样,将所有 01 都转换成 11,所以:

class Solution {
    public boolean makeStringsEqual(String s, String target) {
        int n = s.length();
        int[] cnt = new int[4];
        for(int i = 0; i < n; i++){
            int k = helper(s.charAt(i), target.charAt(i));
            cnt[k]++;
        }

        if(cnt[1] > 0){ // 只要有 1 个 10 或者 11,就能转换所有 01 为 11。否则,01 无法被消除
            if(cnt[2] == 0 && cnt[3] == 0) return false;
            cnt[3] += cnt[1];
        }
    
        // 10 总是能和自己作用并将其中一个变为 00,所以可以当成只有一个 10;只要有一个 11,就能把这个唯一的 10 也消除。
        if(cnt[2] > 0 && cnt[3] == 0) return false;
        return true;
    }
  
    private int helper (char c1, char c2){
        return (c1 - '0') * 2 + (c2 - '0');
    }
}

去掉 while 循环后,复杂度直接变成了

错误代码记录和总结

编码跟不上思路,反复 debugger 的戏码历史又重演了。也许是最近太累了,也许是真的笨,总之非常低级的错误,要反复检查好几遍。被自己蠢哭真的是 emo 了。

image.png

Java
Java
Java
Java
/*
这一版简直就是在乱写了,已经是慌不择路,徒劳挣扎、胡乱提交了
更离谱的是,我在赛场上把这段代码反复提交了两次,挣扎是没用的
*/
class Solution {
    public boolean makeStringsEqual(String s, String target) {
        int n = s.length();
        int[] cnt = new int[4];
        for(int i = 0; i < n; i++){
            int k = helper(s.charAt(i), target.charAt(i));
            cnt[k]++;
        }
        if(cnt[1] > 0){
             if(cnt[2] + cnt[3] < cnt[1])return false;
             cnt[0] = 0; // 事后重看,跟新了 cnt[0],但是后面没有再用到,不知道当时咋想的
        }
  
        if(cnt[2] > 0){
            cnt[2] = 1; // 事后重看,跟新了 cnt[0],但是后面没有再用到,不知道当时咋想的
            if(cnt[3] < 2)return false;
        }
        return true;
  
  
    }
    private int helper (char c1, char c2){
        return (int)(c1 - '0') * 2 + (int)(c2 - '0');
    }
}

T4:题都没来的及看😭

6 分 - 拆分数组的最小代价

据说这道题不难,但我没力气看了。我最近有点刷题刷的走火入魔,或许我需要休息休息了。

祝大家新年快乐~
新年快乐

评论 (23)