对称之美:
已截全。
思路一(究极暴力):
第一眼我想到的是dfs + check。
先进行全排列一遍,每次排列的到的结果进行一次回文判断。
因为我觉得数据量很小,虽然这个解法时间复杂度很高,不过应该是能过。
但结果不尽如人意。
关于dfs的具体思路可以画一个决策树:这样我们分析一个具体的节点即可。
还要注意一些回溯与剪枝的细节,虽然注意了也还是时间复杂度太高了就是了。
代码:
#include <iostream>
#include <vector>
using namespace std;
bool flag = false;
string ret;
void check(string& str)
{
int left = 0, right = str.size() - 1;
while (left < right)
{
if (str[left] == str[right])
{
left++;
right--;
}
else
{
break;
}
}
if (left == right || left == right + 1) flag = true;
}
void dfs(vector<string>& vs, int i)
{
if (i == vs.size() || flag == true) return;
for (auto& val : vs[i])
{
ret.push_back(val);
if (ret.size() == vs.size()) check(ret);
dfs(vs, i + 1);
ret.pop_back();
}
}
int main()
{
int t;
cin >> t;
while (t--)
{
int n, i = 0;
flag = false;
cin >> n;
vector<string> vs(n);
for (int j = 0; j < n; j++) cin >> vs[j];
dfs(vs, i);
if (flag) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}
思路二(双指针+哈希):
这是一个很棒的解法:
我们判断一个字符串是否为回文时,可以利用双指针逐步缩小区间。
将这个解法延伸一下,即使每个是字符串也可以。
为什么?
因为我们将当前left与right对应的字符串进行check是否有相同字符即可。
进行check的策略有二:
其一是进行暴力,也就是两种for循环枚举。
其二是Hash优化。
代码:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
bool check(string& str1, string str2)
{
bool hash1[26] = { false }, hash2[26] = { false };
for (auto& ch : str1) hash1[ch - 'a'] = true;
for (auto& ch : str2) hash2[ch - 'a'] = true;
for (int i = 0; i < 26; i++)
{
if (hash1[i] == true && hash2[i] == true)
{
return true;
}
}
return false;
}
int main()
{
int t;
cin >> t;
while (t--)
{
int n, i = 0;
cin >> n;
vector<string> vs(n);
for (int j = 0; j < n; j++) cin >> vs[j];
int left = 0, right = n - 1;
while (left < right)
{
if (check(vs[left], vs[right]))
{
left++;
right--;
}
else
{
break;
}
}
if (left == right || left == right + 1) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}
非对称之美:
一些错误思路:
对于一些解决回文字符串的常规思路去套是解决不出来的,
比如中心扩展,dp,纯暴力,博主都试过一次,这题的思路更倾向于一个脑筋急转弯?
贪心/规律:
真正的解法很简单
- 判断当前整个字符串是否为回文串,不是的话直接返回当前字符串长度即可。
- 是回文的话我们直接减1即可。
- 对于二来说有一个特例:当整个字符串全部为同一个字母时,需要输出0,因为左边或者右边删掉一个仍旧是回文串。
找到规律就直接变成一个纯纯的代码题了
代码:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str;
cin >> str;
// 进行特殊判断,若是当前字符串为全重复字符那么flag为true。
bool flag = true;
for (int i = 1; i < str.size(); i++)
{
if (str[0] != str[i])
{
flag = false;
break;
}
}
if (flag)
{
cout << 0;
return 0;
}
// 判断当前字符串是否为回文
int left = 0, right = str.size() - 1;
while (left < right)
{
if (str[left] == str[right])
{
left++;
right--;
}
else
{
break;
}
}
if (left == right || left == right + 1) cout << str.size() - 1;
else cout << str.size();
return 0;
}
完~