[杨小白]_leetcode_力扣第 312 场周赛-第四题

120 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第11天,点击查看活动详情

前言

小白算法比较菜,希望能激励我每日更新,从leetcode第一题开始,2022年目标300题,记录从0到1的全过程!!

力扣第 312 场周赛

力扣第 312 场周赛-力扣

a了三题,2000以内,小上10几分。第三题有点离谱,给的例子太基础了,修改了代码之后根本试不出来对不对,错八次可真是,,,,不罚时的话能到1150名呢(当然只能想想)

image.png

这个第四题,,,当又是暴力又是咋,反正就是没做出来。后来看灵山的视频,也没太看懂,经过提醒尝试了一下dp,提交能通过,不是每次都能通过。还是有可能会超时。

image.png

2430. 对字母串可执行的最大删除数

给你一个仅由小写英文字母组成的字符串 s 。在一步操作中,你可以:

  • 删除 整个字符串 s ,或者
  • 对于满足 1 <= i <= s.length / 2 的任意 i ,如果 s 中的 前 i 个字母和接下来的 i 个字母 相等 ,删除 前 i 个字母。 例如,如果 s = "ababc" ,那么在一步操作中,你可以删除 s 的前两个字母得到 "abc" ,因为 s 的前两个字母和接下来的两个字母都等于 "ab" 。

返回删除 s 所需的最大操作数。

示例 1

  • 输入:s = "abcabcdabc"
  • 输出:2

解释:

  • 删除前 3 个字母("abc"),因为它们和接下来 3 个字母相等。现在,s = "abcdabc"。
  • 删除全部字母。 一共用了 2 步操作,所以返回 2 。可以证明 2 是所需的最大操作数。

注意,在第二步操作中无法再次删除 "abc" ,因为 "abc" 的下一次出现并不是位于接下来的 3 个字母。

示例 2

  • 输入:s = "aaabaab"
  • 输出:4

解释:

  • 删除第一个字母("a"),因为它和接下来的字母相等。现在,s = "aabaab"。
  • 删除前 3 个字母("aab"),因为它们和接下来 3 个字母相等。现在,s = "aab"。
  • 删除第一个字母("a"),因为它和接下来的字母相等。现在,s = "ab"。
  • 删除全部字母。

一共用了 4 步操作,所以返回 4 。可以证明 4 是所需的最大操作数。

示例 3

输入: s = "aaaaa"

输出: 5

解释: 在每一步操作中,都可以仅删除 s 的第一个字母。

提示

  • 1 <= s.length <= 4000
  • s 仅由小写英文字母组成

解析

思路其实并不难,从后往前遍历

对于i来说,如果找到能删除到j,那么就更新dp[i] = Math.max(dp[i], dp[j] + 1); 然后一直遍历到数组的最后,此时如果dp[i] 还是0的话,那就一次性全部删除,更新位dp[i] = 1;

从而一直更新到dp[0],返回dp[0]就是删除全部的最大次数了。

代码

代码确实不长,主要在字符串比较太耗时了。

class Solution {
    public int deleteString(String s) {
        char[] chars = s.toCharArray();
        int[] dp = new int[chars.length];
        // Arrays.fill(dp, 1);
        dp[dp.length - 1] = 1;
        int max = 0;
        for (int i = dp.length - 2; i >= 0; i--) {
            dp[i] = 1;
            for (int j = i; j < (dp.length + i >> 1); j++) {
                if (check(i, j, chars)) {
                    dp[i] = Math.max(dp[i], 1 + dp[j + 1]);
                    if (dp[i]>max) break;
                }
            }
            max = Math.max(max,dp[i]);
        }
        return dp[0];
    }

    private boolean check(int i, int j, char[] chars) {
        int l = i;
        int r = j + 1;
        while (l <= j) {
            if (chars[l] != chars[r]) {
                return false;
            }
            r++;
            l++;
        }
        return true;
    }
}

第一、二题连接如下

[杨小白]_leetcode_力扣第 312 场周赛-第一、二题

第三题连接如下

[杨小白]_leetcode_力扣第 312 场周赛-第三题

3.结束

前两题都不难,基本200题量的同学就可以做出来了,第三题的话,最后的方法确实很巧妙,还是得多见多写。第四题虽然没办法做出来非常快和巧妙的技巧,但是要ac还是有机会的,gogogo,刷题刷题,每天一道,三年1000道!!!!