一、题目
给定一个字符串数组 arr
,字符串 s
是将 arr
某一子序列字符串连接所得的字符串,如果 s
中的每一个字符都只出现过一次,那么它就是一个可行解。
请返回所有可行解 s
中最长长度。@wowpH
1、示例1
输入:arr = [“un”,“iq”,“ue”]
输出:4
解释:所有可能的串联组合是 “”,“un”,“iq”,“ue”,“uniq” 和 “ique”,最大长度为 4。
2、示例2
输入:arr = [“cha”,“r”,“act”,“ers”]
输出:6
解释:可能的解答有 “chaers” 和 “acters”。@pfdvnah
3、示例3
输入:arr = [“abcdefghijklmnopqrstuvwxyz”]
输出:26
4、提示
1 <= arr.length <= 16
1 <= arr[i].length <= 26
arr[i]
中只含有小写英文字母
二、题解
根据提示可以看到数据不是很大。可以考虑使用 回溯算法 。至于题目的隐藏提示说的用DP,我暂时没考虑。
回溯思路很简单。
每个字符串有两种情况。
1、加到字符串 s
中
2、不加到字符串 s
中。
按照这两种情况试探即可。@wowpH
用一个大小为26的 boolean
型数组保存已经在字符串 s
中字符的情况。true
表示字符串 s
中有该字符。
时间复杂度:
O
(
2
n
)
O(2^n)
O(2n)
空间复杂度:
O
(
n
)
O(n)
O(n)
三、Java代码
/**
* @link: https://blog.csdn.net/pfdvnah/article/details/102787485
* @date: 2019年10月29日12:16:54
* @author: wowpH
* @author: pfdvnah
*/
class Solution {
public int maxLength(List<String> list) {
return backtrack(list, 0, new boolean[26]);
}
private int backtrack( List<String> list,
int depth,
boolean[] flag) {// 对应字符是否已存在
if (depth == list.size()) {// 超出范围
return 0;
}
// 不连接第depth个字符串
int ret1 = backtrack(list, depth + 1, flag);
// 尝试连接第depth个字符串
char[] arr = list.get(depth).toCharArray();
boolean[] nFlag = flag.clone();// 避免改变原数据
for (char ch : arr) {
// 已存在,说明第depth个字符串不符合要求
if (nFlag[ch - 'a']) {
return ret1;// 返回不连接的最大长度
}// @pfdvnah
nFlag[ch - 'a'] = true;// 设为存在
}
// 连接第depth个字符串
int ret2 = backtrack(list, depth + 1, nFlag);// 新的字符集
return Math.max(ret1, ret2 + arr.length);// 加上当前长度
}
}
四、相关链接
题目链接:https://leetcode-cn.com/contest/weekly-contest-160/problems/maximum-length-of-a-concatenated-string-with-unique-characters/
参考Caloplaca代码:https://leetcode-cn.com/contest/weekly-contest-160/ranking/
原文链接:https://blog.csdn.net/pfdvnah/article/details/102787485