leetcode-1239-串联字符串的最大长度
[博客链接]
[题目描述]
给定一个字符串数组 arr,字符串 s 是将 arr 某一子序列字符串连接所得的字符串,如果 s 中的每一个字符都只出现过一次,那么它就是一个可行解。
请返回所有可行解 s 中最长长度。
示例 1:
输入:arr = ["un","iq","ue"]
输出:4
解释:所有可能的串联组合是 "","un","iq","ue","uniq" 和 "ique",最大长度为 4。
示例 2:
输入:arr = ["cha","r","act","ers"]
输出:6
解释:可能的解答有 "chaers" 和 "acters"。
示例 3:
输入:arr = ["abcdefghijklmnopqrstuvwxyz"]
输出:26
提示:
1 <= arr.length <= 16
1 <= arr[i].length <= 26
arr[i] 中只含有小写英文字母
Related Topics 位运算 回溯算法
👍 110 👎 0
[题目链接]
[github地址]
[思路介绍]
思路一:位运算+递归
-
根据题意分析最终求得的是组合字符串的长度
-
所以我们可以随意打乱字符串字母顺序首先要排除掉包含相同字符串的数组元素
-
因为根据题意这些字符串无法满足我们将每个字符串假想的扩张为长度为26的字符串
-
每个字母放在相对**'a'**的对应位置上定义一个掩码数长度为26位
- 数字位1表示当前位置存在第i个字母
- 数字位0 标识当前位置不存在第i个字母
-
找到所有掩码数后进行递归遍历
-
遍历所有掩码数的标准是,当前掩码数进行与运算
- 如果为0则无公共元素可以选取当前掩码数
- 如果不为0则跳过当前掩码数
-
当然递归转换成迭代也是可以写的在这里就不重复写了
-
数据量不大,记忆化也可以不用暂时
class Solution{
int res = 0;
public int maxLength(List<String> arr) {
List<Integer> masks = new ArrayList<>();
//确立满足条件的字符串
for (String s : arr) {
int mask = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
if ((mask >> (c - 'a') & 1) != 0) {
mask = 0;
break;
}
mask |= (1 << (c - 'a'));
}
if (mask != 0) {
masks.add(mask);
}
}
backTrack(masks,0,0);
return res;
}
public void backTrack(List<Integer> masks, int index, int mask){
//遍历完所有元素,取最大值作为返回
if (index == masks.size()){
res = Math.max(res,Integer.bitCount(mask));
return;
}
//选当前元素
if ((mask & masks.get(index)) == 0){
backTrack(masks,index+1,mask|masks.get(index));
}
//不选当前元素
backTrack(masks,index+1,mask);
}
}
时间复杂度O()