摘要:
本篇文章是对MarsCode AI 刷题中的202题:独一无二的糖葫芦串的题解。
问题描述:
小C有n串长度为m的糖葫芦,每串糖葫芦可以用一个字符串表示。每个糖葫芦的甜度是所有字符甜度的总和,其中每个字符的甜度为该字符与 'a' 的差值。例如,字符 'a' 的甜度为 0,字符 'b' 的甜度为 1,依次类推,字符 'z' 的甜度为 25。
你需要帮助小C找到甜度最大的独一无二的糖葫芦。糖葫芦独一无二当且仅当它与其他n−1根糖葫芦都不同,且翻转后的字符串也不能与其他糖葫芦相同。例如,糖葫芦 "abc" 与 "cba" 视为相同的糖葫芦。
如果没有独一无二的糖葫芦,则返回0。
示例分析:
示例分析:
-
样例1:
-
输入:
n = 3, m = 3, strings = ["ccz", "cba", "zcc"] -
分析:
-
计算甜度:
- "ccz":2 + 2 + 25 = 29
- "cba":2 + 1 + 0 = 3
- "zcc":25 + 2 + 2 = 29
-
判断独一无二:
- "cba"与其反转"abc"不在其他糖葫芦中,且唯一。
-
最大甜度为3。
-
-
-
样例2:
-
输入:
n = 2, m = 3, strings = ["abc", "cba"] -
分析:
- "abc"与"cba"互为反转,均不独一无二。
- 返回0。
-
-
样例3:
-
输入:
n = 5, m = 2, strings = ["aa", "bb", "ab", "ba", "cc"] -
分析:
- "aa"的反转也是"aa",且唯一。
- "bb"的反转也是"bb",且唯一。
- "ab"与"ba"互为反转,均不独一无二。
- "cc"的反转也是"cc",且唯一。
- 甜度分别为0、1、1、1、2。
- 最大甜度为2。
-
题目的背景知识及使用的方法
通过上面的分析,我们可以得出题目的背景知识,具体如下:
背景知识:
- 字符串处理: 理解如何遍历字符串,计算字符的差值,以及字符串的反转。
- 哈希表(HashMap): 用于统计字符串及其反转的出现次数,以判断其唯一性。
- 贪心策略: 在满足条件的情况下,选择具有最大甜度的糖葫芦。
代码执行流程:
-
甜度计算:
- 遍历每个字符串,计算其甜度,即每个字符与
'a'的差值之和。
- 遍历每个字符串,计算其甜度,即每个字符与
-
统计字符串及其反转的出现次数:
- 使用
HashMap记录每个字符串的出现次数。 - 对于每个字符串,计算其反转字符串,并通过哈希表快速查询其是否存在。
- 使用
-
判断独一无二:
- 如果字符串是回文(即自身与反转相同),且只出现一次,则为独一无二。
- 如果字符串不是回文,且自身只出现一次,且反转字符串未出现,则为独一无二。
-
寻找最大甜度:
- 在所有满足独一无二条件的糖葫芦中,选择甜度最大的那个。
- 如果不存在独一无二的糖葫芦,返回0。
代码
import java.util.*;
public class Main {
/**
* 计算字符串的甜度。
*
* @param s 输入字符串
* @return 甜度值
*/
public static int computeSweetness(String s) {
int sum = 0;
for (char c : s.toCharArray()) {
sum += (c - 'a');
}
return sum;
}
/**
* 寻找甜度最大的独一无二的糖葫芦。
*
* @param n 糖葫芦的数量
* @param m 每串糖葫芦的长度
* @param strings 糖葫芦的字符串表示
* @return 最大甜度值,如果没有独一无二的糖葫芦,则返回0
*/
public static int solution(int n, int m, String[] strings) {
// 使用HashMap统计每个字符串的出现次数
HashMap<String, Integer> freqMap = new HashMap<>();
for (String s : strings) {
freqMap.put(s, freqMap.getOrDefault(s, 0) + 1);
}
int maxSweetness = 0;
// 遍历所有唯一的字符串(keySet)
for (String s : freqMap.keySet()) {
String s_rev = new StringBuilder(s).reverse().toString();
if (s.equals(s_rev)) {
// 如果字符串是回文,且只出现一次,则为独一无二
if (freqMap.get(s) == 1) {
int sweetness = computeSweetness(s);
if (sweetness > maxSweetness) {
maxSweetness = sweetness;
}
}
} else {
// 如果字符串不是回文,且自己出现一次,且反转字符串未出现过,则为独一无二
if (freqMap.get(s) == 1 && freqMap.getOrDefault(s_rev, 0) == 0) {
int sweetness = computeSweetness(s);
if (sweetness > maxSweetness) {
maxSweetness = sweetness;
}
}
}
}
return maxSweetness;
}
public static void main(String[] args) {
// 样例测试
System.out.println(solution(3, 3, new String[]{"ccz", "cba", "zcc"}) == 3);
System.out.println(solution(2, 3, new String[]{"abc", "cba"}) == 0);
System.out.println(solution(5, 2, new String[]{"aa", "bb", "ab", "ba", "cc"}) == 4);
}
}
总结
关键点回顾
-
字符串处理技巧:
- 甜度计算: 理解如何通过字符差值计算字符串的甜度,是解决问题的基础。
- 字符串反转与回文判断: 需要掌握如何反转字符串以及判断字符串是否为回文,这在判断独一无二性时尤为重要。
-
哈希表的应用:
- 频率统计: 使用
HashMap统计字符串出现的次数,可以高效地判断字符串的唯一性及其反转字符串的存在性。 - 快速查找: 哈希表提供了O(1)的查找时间复杂度,极大地提升了算法的效率。
- 频率统计: 使用
-
贪心策略的应用:
- 最大化甜度: 在满足独一无二条件的糖葫芦中,选择甜度最大的一个,这是贪心策略的典型应用。
提升指南
-
加强字符串处理能力:
- 练习不同类型的字符串操作题目: 如字符串反转、子串查找、回文判断等。
- 掌握Java中
StringBuilder的使用: 熟悉其反转方法和高效的字符串操作技巧。
-
深入理解哈希表的应用:
- 学习
HashMap的各种方法: 如getOrDefault、put、containsKey等,理解其内部实现机制。 - 对于
HashMap,还可以使用merge方法,对可能出现的getOrDefault和put进行优化,降低代码复杂度。
- 学习
(使用AI生成的优化算法设计)
-
优化算法设计:
- 时间和空间复杂度分析: 学会分析和优化算法的时间复杂度和空间复杂度,确保在大规模数据下仍能高效运行。
- 思考是否有更优解法: 例如,本题是否可以通过其他数据结构(如双向映射)来进一步优化。
AI给出的学习建议
学习建议:
-
多练习字符串处理题目:
- 加深理解: 通过大量练习,熟悉各种字符串操作技巧,如反转、子串查找、回文判断等。
- 掌握高效算法: 学习并掌握高效的字符串处理算法,提升代码执行效率。
-
理解并应用哈希表:
- 频率统计: 练习使用哈希表进行频率统计,解决类似找出唯一元素、重复元素等问题。
- 优化查找: 学会利用哈希表的快速查找特性,优化算法的时间复杂度。
-
掌握贪心策略:
- 最大化目标: 练习贪心算法题目,理解如何在满足条件的前提下,选择最优解。
- 应用场景: 学会识别何时适用贪心策略,提升解题的灵活性和效率。
-
分析算法复杂度:
- 时间复杂度: 学会分析代码的时间复杂度,确保算法在大数据量下仍能高效运行。
- 空间复杂度: 关注算法的空间使用,优化内存占用,提升程序的整体性能。
通过MarsCode AI刷题,我不仅能够系统地练习和巩固编程知识,还能通过智能解析和即时反馈,持续优化自己的解题思路和代码实现。结合系统的学习计划和多样化的复习策略,我能够高效地提升编程能力,逐步掌握复杂算法和数据结构,为未来的编程挑战打下坚实的基础。MarsCode AI 成为我学习编程过程中不可或缺的助手,助力我在编程之路上不断前行。