让人头疼的回文对(leetcode 336)

今天遇到算法bug,查错用了好久。添加链接描述


给定一组 互不相同 的单词, 找出所有不同 的索引对(i, j),使得列表中的两个单词, words[i] + words[j] ,可拼接成回文串。

示例 1:

输入:["abcd","dcba","lls","s","sssll"]
输出:[[0,1],[1,0],[3,2],[2,4]] 
解释:可拼接成的回文串为 ["dcbaabcd","abcddcba","slls","llssssll"]


示例 2:

输入:["bat","tab","cat"]
输出:[[0,1],[1,0]] 
解释:可拼接成的回文串为 ["battab","tabbat"]

看了题目之后,我没有一点头绪,不想用暴力解法,直接看了题解,确实不好想。

逻辑是一个字符串,拆成两部分,其中一部分是回文串,另一部分,反向字符串存在数组中,即满足题目条件
以“sssll”来举例说明

sssll  拆分成 s + ssll

s是回文串,若数组中存在 ssll的反向串,即llss,那就满足条件 即 llss + sssll 就是回文
ssll不是回文串,舍弃。
sssll  拆分成 ss + sll

ss是回文串,若数组中存在 sll的反向串,即lls,那就满足条件 即 lls + sssll 就是回文
sll不是回文串,舍弃。

以此类推

sssll  拆分成 sss + ll

sss是回文串,若数组中存在 ll的反向串,即ll,那就满足条件 即 ll + sssll 就是回文
ll是回文串,若数组中存在 sss的反向串,即sss,就满足条件 sssll + sss 就是回文

上代码

public List<List<Integer>> palindromePairs(String[] words) {
        // 反向单词放到 哈希表中
        Map<String,Integer> map = new HashMap<>();
        int len = words.length;
        for(int i = 0; i < len; i++){
            String re_item = new StringBuilder(words[i]).reverse().toString();
            map.put(re_item, i);
        }
        List<List<Integer>> res = new ArrayList<>();
        // 边界有回文,剩余部分,以反向表中存在,那就有结果
        for(int i = 0; i < len; i++){
            String word = words[i];
            int n = word.length();
            if(n == 0) continue;
           
            for(int j = -1; j < n; j++){
                //左边界至j 是回文
                if(isPalindrome(word, 0, j)){
                    String sub = word.substring(j + 1);
                    int subIndex = hasReverse(map, sub);
                    if(subIndex != -1 && subIndex != i){
                        res.add(Arrays.asList(subIndex,i));
                    }
                }
                // 右边界至j 是回文
                if(isPalindrome(word, j + 1, n -1)){
                    String sub = word.substring(0, j + 1);
                    int subIndex = hasReverse(map, sub);
                    if(subIndex != -1 && subIndex != i){
                        res.add(Arrays.asList(i,subIndex));
                    }
                }
            }
            
        }
        return res.stream().distinct().collect(Collectors.toList());
    }

	/*
	*数组中是否含有反向串
	*/
    private int hasReverse(Map<String,Integer> map, String item){
        return map.getOrDefault(item, -1);
    }
    
	/*
	* 是不是回文串
	*/
    private boolean isPalindrome (String word, int left, int right){
        while(left < right){
            if(word.charAt(left++) != word.charAt(right--)){
                return false;
            }
        }
        return true;
    }

我遇到的bug是[“a”,""],这种情况下,正确结果应该是 [0,1] 和[1,0] ,但是我原来的代码只能出来一个,另外一个出不来。

原代码  for(int j = 0; j < n; j++)
修改为  for(int j = -1; j < n; j++)

引入的问题,是结果重复。

原代码  return res;
修改为  return res.stream().distinct().collect(Collectors.toList());

结果算是通过了,准备睡觉,不再优化。其实可以优化到不产生重复结果的,没心电去扣细节了。

你可能感兴趣的:(算法与数据结构)