【C/C++】5242. 兼具大小写的最好英文字母

310 阅读4分钟

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


题目链接:5242. 兼具大小写的最好英文字母

题目描述

给你一个由英文字母组成的字符串 s ,请你找出并返回 s 中的 最好 英文字母。返回的字母必须为大写形式。如果不存在满足条件的字母,则返回一个空字符串。

最好 英文字母的大写和小写形式必须 s 中出现。

英文字母 b 比另一个英文字母 a 更好 的前提是:英文字母表中,ba 出现。

提示:

  • 1s.length10001 \leqslant s.length \leqslant 1000
  • s 由小写和大写英文字母组成

示例 1:

输入: s = "lEeTcOdE"
输出: "E"
解释:
字母 'E' 是唯一一个大写和小写形式都出现的字母。

示例 2:

输入:s = "arRAzFif"
输出:"R"
解释:
字母 'R' 是大写和小写形式都出现的最好英文字母。
注意 'A''F' 的大写和小写形式也都出现了,但是 'R''F''A' 更好。

示例 3:

输入: s = "AbCdEfGhIjK"
输出: ""
解释:
不存在大写和小写形式都出现的字母。

整理题意

题目给定一个仅由小写和大写英文字母组成的字符串 s ,要求在字符串中找到一个英文字母,它的小写和大写都存在于字符串中,返回它的大写字母,如果存在多个满足条件的答案,返回字典序最大的。

解题思路分析

该题可以使用常规的 哈希表 做法,统计大小写字母,找到大小写字母都存在且字典序最大的字母,返回其大写形式即可。该做法需要记录每个大小写字母的出现情况,空间复杂度为 O(n)O(n)n 为大小写字母数量总和。

优化空间复杂度为 O(1)O(1)

使用 二进制状态压缩位运算 进行优化:

  1. 将大小写字母对应到二进制中的每一位,大小写字母总和最大 52 个,总共就需要二进制下 52 位来存储每个字母是否存在。(也可以用两个 int 型来分别存储大写字母和小写字母)

需要注意 int 有符号整型变量最多只能存储 31 位二进制,有一位为符号位;无符号整型存储 32 位二进制。这里需要 52 位二进制来存储所有字母的出现情况,所以如果只用一个整数的话需要使用更大的 long long int 来存储,有符号的 long long int63 位,无符号的有 64 位。

  1. 在二进制下 0 表示字符串中不存在,1 表示存在,遍历字符串记录每个字母的出现情况;
  2. 将二进制中对应的大写字母和小写字母进行 运算操作,只有当大小写字母同时存在时,与运算结果才为 1
  3. 找到字典序最大的字母也就是与运算后二进制最高位 1 所在的位数,返回对应的大写字母即可。

具体实现

复杂度分析

  • 时间复杂度:O(n)O(n)n 为字符串 s 的长度,需要遍历一遍字符串 s
  • 空间复杂度:
    • 使用常规哈希表做法为 O(n)O(n)n 为字符串中不同的大小写字母个数总和。
    • 使用二进制状态压缩和位运算方法为 O(1)O(1),仅需常数存储空间。

代码实现

二进制状态压缩 + 位运算

class Solution {
public:
    string greatestLetter(string s) {
        //lower 记录小写字母,upper 记录大写字母
        int lower = 0, upper = 0;
        int n = s.length();
        for(int i = 0; i < n; i++){
            //小写字母
            if((s[i] >= 'a') && (s[i] <= 'z')){
                lower |= (1 << (s[i] - 'a'));
            }
            //大写字母
            else upper |= (1 << (s[i] - 'A'));
        }
        //与运算&
        upper = upper & lower;
        //不存在大写和小写形式都出现的字母
        if(upper == 0) return "";
        //k记录与运算后二进制的长度
        int k = 0;
        while(upper){
            upper >>= 1;
            k++;
        }
        //长度即为字典序最大的大写字母所在位置
        string ans = "";
        ans += ('A' + k - 1);
        return ans;
    }
};

总结

  • 该题虽然可以使用常规哈希表做法通过,但在面试中如果要求空间复杂度为 O(1)O(1) 的话,我们需要学会运用状态压缩以及位运算来进行解决;
  • 巧妙使用状态压缩来节省空间,位运算来计算满足条件的字母。
  • 测试结果:

微信截图_20220619222214.png

结束语

乐观是一种生活态度。拥有好心态,让我们能够重新审视烦心事,摆脱郁闷情绪。这不仅会给我们的生活带来明朗和幸福,还会给身边的人带去温暖和希望。保持积极向上的心态,才能走得更加稳健。