贪心题目:不含 AAA 或 BBB 的字符串

文章目录

题目

标题和出处

标题:不含 AAA 或 BBB 的字符串

出处:984. 不含 AAA 或 BBB 的字符串

难度

4 级

题目描述

要求

给定两个整数 a \texttt{a} a 和 b \texttt{b} b,返回任意 满足以下要求的字符串 s \texttt{s} s:

  • s \texttt{s} s 的长度为 a + b \texttt{a} + \texttt{b} a+b,且正好包含 a \texttt{a} a 个字母 'a' \texttt{`a'} 'a' 与 b \texttt{b} b 个字母 'b' \texttt{`b'} 'b'。
  • 子串 "aaa" \texttt{"aaa"} "aaa" 没有出现在 s \texttt{s} s 中。
  • 子串 "bbb" \texttt{"bbb"} "bbb" 没有出现在 s \texttt{s} s 中。

示例

示例 1:

输入: a = 1, b = 2 \texttt{a = 1, b = 2} a = 1, b = 2

输出: "abb" \texttt{"abb"} "abb"

解释: "abb" \texttt{"abb"} "abb"、 "bab" \texttt{"bab"} "bab" 和 "bba" \texttt{"bba"} "bba" 都是正确答案。

示例 2:

输入: a = 4, b = 1 \texttt{a = 4, b = 1} a = 4, b = 1

输出: "aabaa" \texttt{"aabaa"} "aabaa"

数据范围

  • 0 ≤ a, b ≤ 100 \texttt{0} \le \texttt{a, b} \le \texttt{100} 0≤a, b≤100
  • 对于给定的 a \texttt{a} a 和 b \texttt{b} b,保证存在满足要求的 s \texttt{s} s

解法

思路和算法

这道题要求构造字符串 s s s,满足由 a a a 个字母 'a' \text{`a'} 'a' 和 b b b 个字母 'b' \text{`b'} 'b' 组成,且不存在三个相同的连续字母,因此相同字母最多连续出现两次。

在 b b b 的值确定的情况下, a a a 的值最大时对应的 s s s 由 b b b 组 "aab" \text{``aab"} "aab" 以及一组 "aa" \text{``aa"} "aa" 构成,此时 s s s 的长度是 a + b = 3 b + 2 a + b = 3b + 2 a+b=3b+2,因此 a = 2 b + 2 a = 2b + 2 a=2b+2。当 b = 0 b = 0 b=0 时也适用。

同理可知,在 a a a 的值确定的情况下, b b b 的最大值是 2 a + 2 2a + 2 2a+2。

因此非负整数 a a a 和 b b b 满足 0 ≤ a ≤ 2 b + 2 0 \le a \le 2b + 2 0≤a≤2b+2 和 0 ≤ b ≤ 2 a + 2 0 \le b \le 2a + 2 0≤b≤2a+2。

当 a = b a = b a=b 时,用 x x x 表示每个字母的出现次数,则 s s s 可以由 x x x 组 "ab" \text{``ab"} "ab" 构成,此时 s s s 中的任意两个相邻字母都不相同。

当 a ≠ b a \ne b a=b 时,出现次数较多的字母将在 s s s 中连续出现,构造时应满足相同字母最多连续出现两次。以下考虑 a > b a > b a>b 的情况,对于 a < b a < b a<b 的情况做法相同,只要将两个字母交换即可。

  1. 当 a > b > 0 a > b > 0 a>b>0 时,每次将一组 "aab" \text{``aab"} "aab" 拼接到 s s s 的末尾,则每次使用两个 'a' \text{`a'} 'a' 和一个 'b' \text{`b'} 'b',因此将 a a a 的值减 2 2 2,将 b b b 的值减 1 1 1,此时 s s s 中不存在三个相同的连续字母。重复该操作,直到 a = b a = b a=b 或 b = 0 b = 0 b=0。

  2. 如果 a = b a = b a=b,则每次将一组 "ab" \text{``ab"} "ab" 拼接到 s s s 的末尾,每次使用一个 'a' \text{`a'} 'a' 和一个 'b' \text{`b'} 'b',因此将 a a a 的值减 1 1 1,将 b b b 的值减 1 1 1,此时 s s s 中不存在三个相同的连续字母。重复该操作,直到 a = b = 0 a = b = 0 a=b=0。

  3. 如果 a > 0 a > 0 a>0 且 b = 0 b = 0 b=0,则将剩余的 'a' \text{`a'} 'a' 拼接到 s s s 的末尾。

上述做法使用贪心策略,贪心策略的正确性说明如下。

  1. 当 a > b > 0 a > b > 0 a>b>0 时,每次将一组 "aab" \text{``aab"} "aab" 拼接到 s s s 的末尾,因此 s s s 为空或者 s s s 的最后一个字母是 'b' \text{`b'} 'b'。由于每一次拼接的两个或三个字母都以 'a' \text{`a'} 'a' 开始且最多有两个连续的 'a' \text{`a'} 'a',因此不会出现三个相同的连续字母。

  2. 由于保证存在满足要求的 s s s,因此当 a > 0 a > 0 a>0 且 b = 0 b = 0 b=0 时,必有 a ≤ 2 a \le 2 a≤2,此时 s s s 为空或者 s s s 的最后一个字母是 'b' \text{`b'} 'b',将剩余的 'a' \text{`a'} 'a' 拼接到 s s s 的末尾不会出现三个相同的连续字母。

代码

java 复制代码
class Solution {
    public String strWithout3a3b(int a, int b) {
        StringBuffer sb = new StringBuffer();
        while (a > b && b > 0) {
            sb.append("aab");
            a -= 2;
            b--;
        }
        while (b > a && a > 0) {
            sb.append("bba");
            b -= 2;
            a--;
        }
        while (a > 0 && b > 0) {
            sb.append("ab");
            a--;
            b--;
        }
        while (a > 0) {
            sb.append("a");
            a--;
        }
        while (b > 0) {
            sb.append("b");
            b--;
        }
        return sb.toString();
    }
}

复杂度分析

  • 时间复杂度: O ( a + b ) O(a + b) O(a+b),其中 a a a 和 b b b 分别是 s s s 中的字母 'a' \text{`a'} 'a' 和字母 'b' \text{`b'} 'b' 的个数。需要构造长度为 a + b a + b a+b 的字符串,拼接每个字母的时间是 O ( 1 ) O(1) O(1)。

  • 空间复杂度: O ( a + b ) O(a + b) O(a+b),其中 a a a 和 b b b 分别是 s s s 中的字母 'a' \text{`a'} 'a' 和字母 'b' \text{`b'} 'b' 的个数。需要创建一个长度为 a + b a + b a+b 的 StringBuffer \texttt{StringBuffer} StringBuffer 或 StringBuilder \texttt{StringBuilder} StringBuilder 类型的对象。由于 Java 中的 String \texttt{String} String 类型的对象不可变,因此空间复杂度至少为 O ( a + b ) O(a + b) O(a+b)。

相关推荐
伟大的车尔尼7 小时前
贪心题目:救生艇
贪心
Jasmine_llq14 小时前
《P8816 [CSP-J 2022] 上升点列》
数据结构·算法·贪心·排序·二维动态规划 dp·类背包状态转移
lvwangshu2 天前
字符串 题解
字符串·trie·题解·贪心·技巧·性质题·思维好题
Tisfy6 天前
LeetCode 2333.最小差值平方和:排序 + 数学计算(不用二分)
数学·算法·leetcode·题解·贪心·排序
伟大的车尔尼7 天前
贪心题目:单调递增的数字
贪心
Tisfy7 天前
LeetCode 3727.最大交替平方和:排序 (双指针可选)
算法·leetcode·题解·贪心·数组·排序
jyyyx的算法博客11 天前
机器人开箱子【贪心 + 模拟】
贪心·模拟
伟大的车尔尼14 天前
贪心题目:使绳子变成彩色的最短时间
贪心
Tisfy16 天前
LeetCode 0678.有效的括号字符串:O(n)+O(1)一次遍历
算法·leetcode·字符串·题解·贪心·括号匹配
伟大的车尔尼16 天前
贪心题目:坏了的计算器
贪心