【每日一题】LeetCode 2024.考试的最大困扰度(字符串、二分查找、前缀和、滑动窗口)

【每日一题】LeetCode 2024.考试的最大困扰度(字符串、二分查找、前缀和、滑动窗口)

题目描述

一位老师正在出一场由 n 道判断题构成的考试,每道题的答案为 true (用 'T' 表示)或者 false (用 'F' 表示)。老师想增加学生对自己做出答案的不确定性,方法是 最大化连续相同 结果的题数。(也就是连续出现 true 或者连续出现 false)。

给定一个由 ‘T’ 和 ‘F’ 组成的字符串 answerKey,表示一系列判断题的答案。我们的目标是通过最多 k 次操作,使得字符串中连续的相同字符(‘T’ 或 ‘F’)的最大数量最大化。每次操作可以改变一个字符的值。

思路分析

这个问题可以通过动态规划、贪心算法、滑动窗口来解决。这里我们采用滑动窗口算法的思路:

  1. 贪心策略:我们希望最大化连续相同字符的数量,因此我们可以考虑两种情况:将所有的 ‘F’ 转换为 ‘T’ 或者将所有的 ‘T’ 转换为 ‘F’。这样,我们只需要考虑两种情况中的最优解。

  2. 滑动窗口:使用滑动窗口来维护当前窗口内连续相同字符的数量。窗口的左边界和右边界分别表示窗口的起始和结束位置。

    滑动窗口算法分析

    1. 初始化:定义两个指针 ij 分别代表窗口的右边界和左边界,以及一个计数器 cnt 来记录窗口内与目标字符不同的字符数量。
    2. 遍历字符串:通过遍历字符串,将每个字符与目标字符(‘T’ 或 ‘F’)进行比较。
    3. 更新窗口:如果当前字符与目标字符相同,则增加 cnt。如果不同,则尝试通过移动窗口的左边界(即增加 j)来减少 cnt,直到窗口内的不同字符数量不超过 k
    4. 计算最大长度:在每次移动窗口的过程中,更新并记录当前窗口的最大长度,这个长度就是当前条件下能够达到的最大连续相同字符的数量。
    5. 返回结果:最后,返回在两种情况下(将 ‘F’ 转换为 ‘T’ 和将 ‘T’ 转换为 ‘F’)的最大连续数量中的较大者。

输入示例

示例 1:

输入:answerKey = "TTFF", k = 2
输出:4
解释:我们可以将两个 'F' 都变为 'T' ,得到 answerKey = "TTTT" 。
总共有四个连续的 'T' 。

示例 2:

输入:answerKey = "TFFT", k = 1
输出:3
解释:我们可以将最前面的 'T' 换成 'F' ,得到 answerKey = "FFFT" 。
或者,我们可以将第二个 'T' 换成 'F' ,得到 answerKey = "TFFF" 。
两种情况下,都有三个连续的 'F' 。

示例 3:

输入:answerKey = "TTFTTFTT", k = 1
输出:5
解释:我们可以将第一个 'F' 换成 'T' ,得到 answerKey = "TTTTTFTT" 。
或者我们可以将第二个 'F' 换成 'T' ,得到 answerKey = "TTFTTTTT" 。
两种情况下,都有五个连续的 'T' 。

代码实现

class Solution {
    public int maxConsecutiveAnswers(String answerKey, int k) {
        // 将字符串转换为字符数组
        char[] chars = answerKey.toCharArray();
        // 分别计算将所有 'F' 转换为 'T' 和将所有 'T' 转换为 'F' 的最大连续数量
        return Math.max(getCnt(chars, 'T', k), getCnt(chars, 'F', k));
    }

    // 计算将指定字符转换为 c 的最大连续数量
    private int getCnt(char[] chars, char c, int k) {
        int ans = 0; // 用于存储最大连续数量
        for (int i = 0, j = 0, cnt = 0; i < chars.length; i++) {
            // 如果当前字符与目标字符相同,增加计数
            if (chars[i] == c) {
                cnt++;
            }
            // 当连续相同字符的数量超过 k 时,移动窗口左边界
            while (cnt > k) {
                if (chars[j] == c) {
                    cnt--;
                }
                j++;
            }
            // 更新最大连续数量
            ans = Math.max(ans, i - j + 1);
        }
        return ans;
    }
}
  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值