题解 | #小红的大小写字母#

小红的大小写字母

https://www.nowcoder.com/practice/e82a7b09d26c4b20b5b4abc468ee6619

题目链接

小红的大小写字母

题目描述

小红拿到了一个仅由大小写字母构成的长度为 的字符串,她每次操作可以将一个字符在大小写之间切换(例如将 'a' 变为 'A',或将 'A' 变为 'a')。

她希望经过恰好 次操作后,大写字母的数量尽可能多。请输出最终字符串中大写字母的数量。

输入:

  • 两个整数
  • 一个长度为 、由大小写字母构成的字符串

输出:

  • 一个整数,表示经过恰好 次操作后,最终字符串中大写字母的最大数量。

解题思路

这是一个需要一些逻辑推理的贪心问题。问题的关键在于,我们不仅要最大化大写字母的数量,还必须确保总操作次数恰好为

我们可以反向思考:假设我们最终的目标是得到 个大写字母,这个目标是否可行?需要满足什么条件?

  1. 计算初始状态:首先,我们遍历一次字符串,统计出初始的大写字母数量,记为

  2. 计算最小操作数: 要想从 个大写字母的状态,转变为 个大写字母的状态,最少需要多少次操作?

    • 这个最直接的方式就是只翻转那些状态不对的字母。例如,如果 ,我们就需要把 个小写字母变成大写。
    • 因此,这个最少的必要操作次数就是 。我们将其记为
  3. 处理剩余操作数:我们总共有 次操作。在完成了 次必要操作后,还剩下 次操作。由于题目要求必须用完恰好 次操作,这些剩余的操作必须被“浪费”掉。

    • 如何“浪费”操作而不影响最终结果呢?我们可以对同一个字母进行一次往返操作,例如 。这样的操作消耗 2 次,但字母的最终状态不变。
    • 这意味着,所有剩余的操作 都必须能这样成对地消耗掉。因此, 必须是一个非负偶数
  4. 得出可行性条件:综上所述,一个目标大写字母数量 是可行的,当且仅当同时满足以下两个条件:

    • (总操作次数必须足够)
    • (剩余的操作次数必须是偶数)
  5. 寻找最优解:题目要求我们最大化 。因此,我们可以从大到小(从 )遍历所有可能的 值。第一个满足上述两个条件的 ,就是我们能得到的最大大写字母数量。

代码

#include <iostream>
#include <string>
#include <cmath>
#include <algorithm>

using namespace std;

void solve() {
    int n;
    long long k;
    cin >> n >> k;
    string s;
    cin >> s;

    int upper_count = 0;
    // 统计初始大写字母数量
    for (char c : s) {
        if (c >= 'A' && c <= 'Z') {
            upper_count++;
        }
    }

    // 从 n 到 0 遍历所有可能的大写字母目标数量 T
    for (int T = n; T >= 0; --T) {
        // 计算达到目标 T 所需的最小操作次数
        long long min_ops = abs(T - upper_count);
        
        // 检查是否满足两个条件:
        // 1. 总操作次数 k 不少于最小操作次数
        // 2. 剩余的操作次数 (k - min_ops) 是偶数,可以成对抵消
        if (k >= min_ops && (k - min_ops) % 2 == 0) {
            cout << T << endl;
            return;
        }
    }
}

int main() {
    solve();
    return 0;
}
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt();
        long k = sc.nextLong();
        String s = sc.next();

        int upper_count = 0;
        // 统计初始大写字母数量
        for (int i = 0; i < n; i++) {
            if (Character.isUpperCase(s.charAt(i))) {
                upper_count++;
            }
        }

        // 从 n 到 0 遍历所有可能的大写字母目标数量 T
        for (int T = n; T >= 0; T--) {
            // 计算达到目标 T 所需的最小操作次数
            long min_ops = Math.abs(T - upper_count);
            
            // 检查是否满足两个条件:
            // 1. 总操作次数 k 不少于最小操作次数
            // 2. 剩余的操作次数 (k - min_ops) 是偶数,可以成对抵消
            if (k >= min_ops && (k - min_ops) % 2 == 0) {
                System.out.println(T);
                return;
            }
        }
    }
}
def solve():
    n, k = map(int, input().split())
    s = input()

    upper_count = 0
    # 统计初始大写字母数量
    for char in s:
        if 'A' <= char <= 'Z':
            upper_count += 1
    
    # 从 n 到 0 遍历所有可能的大写字母目标数量 T
    for T in range(n, -1, -1):
        # 计算达到目标 T 所需的最小操作次数
        min_ops = abs(T - upper_count)
        
        # 检查是否满足两个条件:
        # 1. 总操作次数 k 不少于最小操作次数
        # 2. 剩余的操作次数 (k - min_ops) 是偶数,可以成对抵消
        if k >= min_ops and (k - min_ops) % 2 == 0:
            print(T)
            return

solve()

算法及复杂度

  • 算法:贪心、枚举
  • 时间复杂度: ,其中 是字符串的长度。统计初始大写字母数量需要 ,之后从 向下遍历寻找可行解最多也需要
  • 空间复杂度: ,用于存储输入的字符串。
全部评论

相关推荐

刚刷到字节跳动官方发的消息,确实被这波阵仗吓了一跳。在大家还在纠结今年行情是不是又“寒冬”的时候,字节直接甩出了史上规模最大的转正实习计划——ByteIntern。咱们直接看几个最硬的数,别被花里胡哨的宣传词绕晕了。首先是“量大”。全球招7000多人是什么概念?这几乎是把很多中型互联网公司的总人数都给招进来了。最关键的是,这次的资源分配非常精准:研发岗给了4800多个Offer,占比直接超过六成。说白了,字节今年还是要死磕技术,尤其是产品和AI领域,这对于咱们写代码的同学来说,绝对是今年最厚的一块肥肉。其次是大家最关心的“转正率”。官方直接白纸黑字写了:整体转正率超过50%。这意味着只要你进去了,不划水、正常干,每两个人里就有一个能直接拿校招Offer。对于2027届(2026年9月到2027年8月毕业)的同学来说,这不仅是实习,这简直就是通往大厂的快捷通道。不过,我也得泼盆冷水。坑位多,不代表门槛低。字节的实习面试出了名的爱考算法和工程实操,尤其是今年重点倾斜AI方向,如果你简历里有和AI相关的项目,优势还是有的。而且,转正率50%也意味着剩下那50%的人是陪跑的,进去之后的考核压力肯定不小。一句话总结:&nbsp;27届的兄弟们,别犹豫了。今年字节这是铁了心要抢提前批的人才,现在投递就是占坑。与其等到明年秋招去千军万马挤独木桥,不如现在进去先占个工位,把转正名额攥在手里。
喵_coding:别逗了 50%转正率 仔细想想 就是转正与不转正
字节7000实习来了,你...
点赞 评论 收藏
分享
评论
3
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务