LeetCode第245场周赛(6.13)总结

前言

只写前三题,第四题实力不够暂时不写

第一题 1897. 重新分配字符使所有字符串都相等(简单)

给你一个字符串数组 words(下标 从 0 开始 计数)。
在一步操作中,需先选出两个 不同 下标 i 和 j,其中 words[i] 是一个非空字符串,接着将 words[i] 中的 任一 字符移动到 words[j] 中的 任一 位置上。
如果执行任意步操作可以使 words 中的每个字符串都相等,返回 true ;否则,返回 false 。
提示:
1 <= words.length <= 100
1 <= words[i].length <= 100
words[i] 由小写英文字母组成

当时思路

先分析,只需要得出能否达成目标,不需要取出最小操作步骤之类的,很显然只需要每个字母能均匀的分散到各个words就可以。
再看问题规模,长度在一百以内,每个词长度也在一百以内,遍历一遍操作次数在10000以内,可以直接遍历
直接取出每个字母出现的次数,每个出现次数非0的值看看能否平均分布就可

class Solution {
    public boolean makeEqual(String[] words) {
        int[] array = new int[26];
        for (String word : words) {
            for (int i = 0; i < word.length(); i++) {
                array[word.charAt(i) - 'a']++;
            }
        }
        int len = words.length;
        for (int i = 0; i < array.length; i++) {
            if(array[i] % len != 0){
                return false;
            }
        }
        return true;
    }
}

第二题 1898. 可移除字符的最大数目(中等)

给你两个字符串 s 和 p ,其中 p 是 s 的一个 子序列 。同时,给你一个元素 互不相同 且下标 从 0 开始 计数的整数数组 removable ,该数组是 s 中下标的一个子集(s 的下标也 从 0 开始 计数)。
请你找出一个整数 k(0 <= k <= removable.length),选出 removable 中的 前 k 个下标,然后从 s 中移除这些下标对应的 k 个字符。整数 k 需满足:在执行完上述步骤后, p 仍然是 s 的一个 子序列 。更正式的解释是,对于每个 0 <= i < k ,先标记出位于 s[removable[i]] 的字符,接着移除所有标记过的字符,然后检查 p 是否仍然是 s 的一个子序列。
返回你可以找出的 最大 k ,满足在移除字符后 p 仍然是 s 的一个子序列。
字符串的一个 子序列 是一个由原字符串生成的新字符串,生成过程中可能会移除原字符串中的一些字符(也可能不移除)但不改变剩余字符之间的相对顺序。
提示:
1 <= p.length <= s.length <= 105
0 <= removable.length < s.length
0 <= removable[i] < s.length
p 是 s 的一个 子字符串
s 和 p 都由小写英文字母组成
removable 中的元素 互不相同

当时思路

比赛时先做的第三题,剩下差不多一个小时在这个题目上面,一直没做出来,当时想判断p是否是s的子序列的复杂度为p.length*s.length(这是子串,不是子序列!),这最大到了十亿,只是一次检查就这么多,所以认为此路不通,导致一直没有思路,甚至想到的唯一办法,用dp遍历一次将所有子序列求出来,然后计算每个字母出现次数,再一个个减去removable对应的字母,如果字母出现次数不为0则仍然存在子序列,只是dp的复杂度也没办法降低,更何况空间复杂度也会很高。

正确思路

实际检查子序列的复杂度最大为m+n,所以如果直接暴力,复杂度为removable.length * (p.length + s.length),显然removable这里可以使用二分法,则将复杂度降低为log removable.length * (p.length + s.length)
代码如下,本身可以不用判断reset,只是考虑到取二段后,去标记字符有一段是重复的,例如第一次标记了0-mid间的数,然后取左半段,那么其中只需要清除左半段中的右半部分的标记,减少运算次数,整体仍然是二分的思想,中间使用origin赋值,尽量减少在循环里创建对象,减少内存使用(或者说是内存抖动)

    public int maximumRemovals(String s, String p, int[] removable) {
        char[] sChars = s.toCharArray();
        char[] origin = sChars.clone();
        char[] pChars = p.toCharArray();
        int left = 0;
        int right = removable.length;
        boolean reset = false;
        while (left < right) {
            int mid = ((right - left) >> 1) + left;
            if(reset){
                for (int i = mid + 1; i <= right; i++) {
                    sChars[removable[i]] = origin[removable[i]];
                }
            }else {
                for (int i = left; i <= mid; i++) {
                    sChars[removable[i]] = '#';
                }
            }
            if ((reset = check(sChars, pChars))) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        return left;
    }

第三题 1899. 合并若干三元组以形成目标三元组(中等)

三元组 是一个由三个整数组成的数组。给你一个二维整数数组 triplets ,其中 triplets[i] = [ai, bi, ci] 表示第 i 个 三元组 。同时,给你一个整数数组 target = [x, y, z] ,表示你想要得到的 三元组 。
为了得到 target ,你需要对 triplets 执行下面的操作 任意次(可能 零 次):
选出两个下标(下标 从 0 开始 计数)i 和 j(i != j),并 更新 triplets[j] 为 [max(ai, aj), max(bi, bj), max(ci, cj)] 。
例如,triplets[i] = [2, 5, 3] 且 triplets[j] = [1, 7, 5],triplets[j] 将会更新为 [max(2, 1), max(5, 7), max(3, 5)] = [2, 7, 5] 。
如果通过以上操作我们可以使得目标 三元组 target 成为 triplets 的一个 元素 ,则返回 true ;否则,返回 false 。
提示:
1 <= triplets.length <= 105
triplets[i].length == target.length == 3
1 <= ai, bi, ci, x, y, z <= 1000

当时思路

先仔细看题,思路还是比较容易,只需要取出所有三元素小于等于目标三元素的值,全部取最大值即可
以下是当时的解法,时间复杂度上就是o(n) 空间复杂度o(1) 所以从算法上是最优解法,细节仍然可以优化

class Solution {
    public boolean mergeTriplets(int[][] triplets, int[] target) {
        int[] temp = new int[3];
        int len = triplets.length;
        for (int i = 0; i < len; i++) {
            boolean flag = true;
            for (int j = 0; j < 3; j++) {
                if (triplets[i][j] > target[j]) {
                    flag = false;
                    break;
                }
            }
            if(flag){
                for (int j = 0; j < 3; j++) {
                    temp[j] = Math.max(temp[j], triplets[i][j]);
                }
            }
        }
        for (int i = 0; i < 3; i++) {
            if (temp[i] != target[i]) {
                return false;
            }
        }
        return true;
    }
}

优化思路

在flag的判断中可以加上只有当triplets[i]有起码一个到目的值才进入
在判断的里面,可以改为布尔数组,达到值就可以不做判断直接跳过,这样结果的判断也只需要三个值做且运算
以下为LeetCode中的最优算法,细节做了足够的优化

class Solution {
    public boolean check(int[][]m,int[]c,int idx){
        for(int i=0;i<m.length;i++){
            if(m[i][idx]==c[idx]&&m[i][(idx+1)%3]<=c[(idx+1)%3]&&m[i][(idx+2)%3]<=c[(idx+2)%3])
                return true;
        }
        return false;
    }
    public boolean mergeTriplets(int[][] triplets, int[] target) {
        boolean a=false,b=false,c=false;
        a=check(triplets,target,0);
        b=check(triplets,target,1);
        c=check(triplets,target,2);
        return a&&b&&c;
    }
}

总结

第二题的问题太大了,子串子序列的复杂度就随便想一下,导致后面一个小时挂在这
做的比较好的点是第二题初步计算复杂度认为没思路就看了第三题,迅速完成了第三题。
整体来说本周周赛难度较小,除了第四题,暂时没到第四题的水平

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容