问题描述
小C有n串长度为m的糖葫芦,每串糖葫芦可以用一个字符串表示。每个糖葫芦的甜度是所有字符甜度的总和,其中每个字符的甜度为该字符与 'a' 的差值。例如,字符 'a' 的甜度为 0,字符 'b' 的甜度为 1,依此类推,字符 'z' 的甜度为 25。
你需要帮助小C找到甜度最大的独一无二的糖葫芦。糖葫芦独一无二当且仅当它与其他n−1根糖葫芦都不同,且翻转后的字符串也不能与其他糖葫芦相同。例如,糖葫芦 "abc" 与 "cba" 视为相同的糖葫芦。
如果没有独一无二的糖葫芦,则返回0。
思路
通过一个map来对数据进行存储,键为字符串,值为一个vector<int>列表,但在使用过程中只使用其中的最开头两个值,第一个值作为该字符串出现的次数,包括正反两种顺序,第二个值作为该字符串的甜度,然后进行两重循环遍历初始化map,最终遍历map获取独一无二的糖葫芦的糖度。
代码实现
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
using namespace std;
int solution(int n, int m, vector<string> &strings)
{
// write code here
map<string, vector<int>> up;
int max = 0;
for (auto &s : strings) // 遍历每一个字符串
{
int sugar = 0;
for (auto &c : s) // 遍历字符串中每一个字符
{
sugar += c - 'a'; // 获取甜度
}
string tmp = s;
reverse(tmp.begin(), tmp.end());
if (up.find(tmp) != up.end()) // 判断翻转后的字符串是否已在map中
{
up[tmp][0]++;
}
else
{
up.insert(pair<string, vector<int>>(s, {0, sugar})); // 不在则需要添加内容到map中
up[s][0]++;
}
}
for (auto &a : up) // 最终遍历map获取最大的且独一无二的甜度
{
// cout << a.first << endl;
// cout << a.second[0] << " " << a.second[1] << endl; // 通过这些打印可以查看过程结束后的值
if (a.second[1] > max && a.second[0] == 1)
max = a.second[1]; // 通过两个条件判断更新最大甜度
}
return max;
}
int main() {
vector<string> strings1 = {"ccz", "cba", "zcc"};
cout << (solution(3, 3, strings1) == 3) << endl;
vector<string> strings2 = {"abc", "cba"};
cout << (solution(2, 3, strings2) == 0) << endl;
vector<string> strings3 = {"aa", "bb", "ab", "ba", "cc"};
cout << (solution(5, 2, strings3) == 4) << endl;
}
算法分析
时间复杂度
- 遍历strings数组,共n次,每个字符串m,map查找或插入一个字符串复杂度时O(log(n)),总复杂度为O(n*(m+log(n)))
- 遍历map中的键值对最坏情况下最多为n,处理每个键值对需要O(1),总复杂度为O(n)
- 总时间复杂度为O(n*(m+log(n)))
空间复杂度
- 主要消耗空间位map,存储字符串及相关信息
- 最坏情况为O(n*m)