LeetCode1239串联字符串的最大长度

题目

给定一个字符串数组 arr,字符串 s 是将 arr 某一子序列字符串连接所得的字符串,如果 s 中的每一个字符都只出现过一次,那么它就是一个可行解。

请返回所有可行解 s 中最长长度。

解题

暴力回溯:

f(i,bool[],arr):遍历到arr中第i个字符串,bool数组标识已经出现过的字符。
f(i+1,bool[],arr)+arr[i].length()//如果bool和arr[i]没有冲突,则把arr[i]加入bool[],并且递归
回退bool,
f(i+1.bool[],maxLen,arr)

向上返回两者中大的。

优化用32位的int代表26位的bool[],加上memo。注意单个字符串自己可能就不符合条件,可以用-1表示。

代码:

public static int maxLength(List<String> arr) {
    //得到每个的长度和数字表示
    int n=arr.size();
    int[] len=new int[n];
    int[] present=new int[n];
    for (int i = 0; i < n; i++) {
        len[i]=arr.get(i).length();
        present[i]=toPresent(arr.get(i));
    }
    return maxLength(0,0,len,present);
}
//字符串->int表示哪些字符出现过
private static int toPresent(String s) {
    int res=0;
    for (char ch:s.toCharArray()){
        int tmp=1<<((ch-'a'));
        if((tmp&res)!=0) return -1;
        res|=tmp;
    }
    return res;
}

public static int maxLength(int i,int chars, int[] len,int[] present) {
    if(i==len.length){
        return 0;
    }
    int res1=maxLength(i+1,chars,len,present);
    boolean conflict=(present[i]==-1||(chars&present[i])!=0);

    int res2=0;
    if(!conflict){
        res2=len[i]+maxLength(i+1,chars|present[i],len,present);
    }

    return Math.max(res1,res2);
}

猜你喜欢

转载自www.cnblogs.com/FannyChung/p/leetcode1239.html