解题思路:
本题要求返回的是最长长度,因为每一次再做拼接时候,需要考虑自身的每一个字符是否是不重复的,而且还要考虑,自身字符是否和已存在满足要求的字符串重复,随意需要整个遍历很多次,然后只选择满足要求的部分加入到路径中,选择采用回溯算法
- 注意:
1.注意满足加入路径的条件
2.遍历条件
3.在递归后面加入pop操作
class Solution {
public:
int maxLength(vector<string>& arr) {
int curr = 0;
int res = 0;
vector<string>path;
trace(arr, path, res, 0);
return res;
}
// 回溯算法的核心
void trace(const vector<string> &arr, vector<string>path, int &res, int pos) {
int curr = 0;
for (string s : path) {
curr += s.size();
}
// 更新每一次的路径长度
res = max(res, curr);
for (int i = pos; i < arr.size(); ++i) {
// 加入的条件
if (can_add(arr, path, i) && no_repeat(arr, i)) {
path.push_back(arr[i]);
// 继续递归调用
trace(arr, path, res, i + 1);
// 弹出最后一个符合的元素,加入下一个元素
path.pop_back();
}
}
}
// 判断是否含有重复字符,如果没有可以添加
bool can_add(const vector<string> &arr, vector<string>path, int pos) {
string s = arr[pos];
for (char c : s) {
for (string s : path) {
if (s.find(c) != string::npos)return false;
}
}
return true;
}
// 判断自身是否含有重复的字符,如果没有就符合要求
bool no_repeat(const vector<string> &arr, int pos) {
string s = arr[pos];
unordered_set<char>temp_set(s.begin(), s.end());
return temp_set.size() == s.size() ? true : false;
}
};