Day 7:2745. 构造最长的新字符串

Leetcode 2745. 构造最长的新字符串

给你三个整数 x ,y 和 z 。
这三个整数表示你有 x 个 “AA” 字符串,y 个 “BB” 字符串,和 z 个 “AB” 字符串。你需要选择这些字符串中的部分字符串(可以全部选择也可以一个都不选择),将它们按顺序连接得到一个新的字符串。新字符串不能包含子字符串 “AAA” 或者 “BBB” 。
请你返回 新字符串的最大可能长度。
子字符串 是一个字符串中一段连续 非空 的字符序列。

image.png

深度优先搜索

先选择一个开头,后面继续选择,判断能获得的最大长度。
比如,先选择 “AA”,那么后一个只能选择 “AB” 或 “BB”。迭代计算。

完整代码

class Solution {
    public int longestString(int x, int y, int z) {
        int res = 0;
        if (x > 0) {
            res = Math.max(res, maxLength(0, x - 1, y, z) + 1);
        }
        if (y > 0) {
            res = Math.max(res, maxLength(1, x, y - 1, z) + 1);
        }
        if (z > 0) {
            res = Math.max(res, maxLength(1, x, y, z - 1) + 1);
        }
        return res * 2;
    }

    // before 0 表示上一个字符为 A,1 表示为 B
    public int maxLength(int before, int x, int y, int z) {
        int count = 0;
        if (before == 0) {
            if (y > 0) {
                count = Math.max(count, maxLength(1, x, y - 1, z) + 1);
            }
        } else {
            if (x > 0) {
                count = Math.max(count, maxLength(0, x - 1, y, z) + 1);
            }
            if (z > 0) {
                count = Math.max(count, maxLength(1, x, y, z - 1) + 1);
            }
        }

        return count;
    }
}

此方法对于大的数据会超出时间限制。

动态规划

与深度优先搜索类似,深度因为有很多参数相同的重复计算,因此会浪费时间。
创建一个四维数组用来保存计算结果,避免重复计算。

完整代码

class Solution {
    int[][][][] dp;
    public int longestString(int x, int y, int z) {
        dp = new int[2][x + 1][y + 1][z + 1];
        int res = 0;
        if (x > 0) {
            res = Math.max(res, maxLength(0, x - 1, y, z) + 1);
        }
        if (y > 0) {
            res = Math.max(res, maxLength(1, x, y - 1, z) + 1);
        }
        if (z > 0) {
            res = Math.max(res, maxLength(1, x, y, z - 1) + 1);
        }
        return res * 2;
    }

    // before 0 表示上一个字符为 A,1 表示为 B
    public int maxLength(int before, int x, int y, int z) {
        if (dp[before][x][y][z] != 0) return dp[before][x][y][z];
        int count = 0;
        if (before == 0) {
            if (y > 0) {
                count = Math.max(count, maxLength(1, x, y - 1, z) + 1);
            }
        } else {
            if (x > 0) {
                count = Math.max(count, maxLength(0, x - 1, y, z) + 1);
            }
            if (z > 0) {
                count = Math.max(count, maxLength(1, x, y, z - 1) + 1);
            }
        }
        dp[before][x][y][z] = count;
        return count;
    }
}

增加 1 个 int[2][x + 1][y + 1][z + 1] 的四维数组来保存计算结果,如果已经计算过就直接取值,如果没计算过就计算,并在最后把结果保存进去。

。。。。

不知道取个什么名字好,哈哈哈
解法来自题解。
首先我们只考虑 “AA” 和 “BB” 那么组成的最长长度就是 Math.min(x, y) * 2 + (x != y ? 1 : 0)。“AA" 和 “BB” 拼接,用两个的最小值乘以 2;如果一个比一个多,就可以放在拼接后的某一端,因此加一。
然后将 “AB” 插入其中,会发现,它无能多少个都可以插入进去的,因此直接加 z。

可能会考虑,如果插入 “AB” 后,那么 “AA” 或 “BB” 多的一方。能否多插入。
多的是 “AA”,
在其前面放入一个 “AB”, 再在其前面是无法再放一个 “AA” 的,就算在其前面放入多个 “AB”,也是不能放的。
在其后面放入一个 “AB”,明显不满足。
多的是 “BB”
不能在其前面放入 “AB”.
在其后面放入 “AB”,同样的道理,也是不能再放入一个 “BB” 的。

因此,插入 “AB”,并不能改变前者的数量。

完整代码

class Solution {
    public int longestString(int x, int y, int z) {
        return (Math.min(x, y) * 2 + (x != y ? 1 : 0) + z) * 2;
    }
}
  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值