[leetcode] 336. Palindrome Pairs 解题报告

来源:互联网 发布:netbeans开发php 编辑:程序博客网 时间:2024/05/13 07:51

题目链接: https://leetcode.com/problems/palindrome-pairs/

Given a list of unique words. Find all pairs of distinct indices (i, j) in the given list, so that the concatenation of the two words, i.e. words[i] + words[j] is a palindrome.

Example 1:
Given words = ["bat", "tab", "cat"]
Return [[0, 1], [1, 0]]
The palindromes are ["battab", "tabbat"]

Example 2:
Given words = ["abcd", "dcba", "lls", "s", "sssll"]
Return [[0, 1], [1, 0], [3, 2], [2, 4]]
The palindromes are ["dcbaabcd", "abcddcba", "slls", "llssssll"]



思路: 将所有的单词逆序加入hash表中, 然后再遍历一遍数组, 然后会有两种情况

1. 将单词的前一部分如果可以在hash表中找到匹配说明这部分是可以回文的, 如果这个单词剩下的部分也是回文, 那么这两个单词就可以配成回文. 例如aabbcc和bbaa, 其中bbaa在hash表中是以逆序存在的, 即aabb, 那么当我们遍历到aabbcc的时候其前半部分aabb可以在hash表中查到, 并且剩余部分cc是回文, 因此他们可以构成回文

2. 如果单词的后一部分可以在hash表中查到, 并且其前一部分是回文, 他们也可以构成匹配. 例如aabb和ccbbaa, 其中aabb在hash表中是以bbaa存在的. 当我们遍历到ccbbaa的时候, 其后一部分bbaa可以在hash表中查到存在, 并且其前一部分cc是回文, 因此他们也可以构成回文.


基本的思路就是这样, 但是有一些特殊的case,

1. 要防止与其本身进行匹配

2. 当存在空串时, 就会复杂一些, 比如["a", ""], 这种情况应该输出[[0, 1] [1, 0]]. 因此空串也应该在作为其前缀和后缀进行检测. 但是这种情况又会引起另外的问题, 例如aabb和bbaa, 当我们将单词划分为左右两部分并且其前半部分为空串或这后半部分为空串时都会匹配, 也就是遍历到aabb时会产出两个匹配, 即aabb作为前缀, 空串作为后缀 和空串作为前缀, aabb作为后缀时. 而遍历到单词bbaa时又会重复匹配一次, 因此我们需要引入另外一个条件, 即在分别判断将当前单词的前一部分作为前缀和后一部分作为后缀的时候, 其前缀和后缀不能同时等于单词本身.


OK, 解法就是这样, 虽然在上面我说的是将单词逆序加入hash表, 但是在代码中我其实是正序加入, 然后在遍历的时候翻转字符串的. 这样做的好处是可以减少代码量, 看起来不那么复杂, 哈哈! 到现在为止, 我基本算是将leetcode刷完一遍了, 有几题没有写解题报告, 接下来刷第二遍的时候我都会补上, 并且会完善我之前的解题报告.

代码如下:

class Solution {public:    bool isPalin(string& str)    {        for(int i = 0; i < str.size()/2; i++)            if(str[i] != str[str.size()-i-1]) return false;        return true;    }        vector<vector<int>> palindromePairs(vector<string>& words) {        unordered_map<string, int> hash;        vector<vector<int>> result;        for(int i =0; i< words.size(); i++) hash[words[i]] = i;        for(int i =0; i< words.size(); i++)        {            reverse(words[i].begin(), words[i].end());            int len = words[i].size();            for(int j = 0; j<= len; j++)            {                string left =words[i].substr(0, j), right = words[i].substr(j);                if(hash.count(left) &&isPalin(right) &&hash[left]!=i &&len>= j)                    result.push_back(vector<int>{hash[left], i});                if(hash.count(right) &&isPalin(left) &&hash[right]!=i &&len>len-j)                    result.push_back(vector<int>{i, hash[right]});            }        }        return result;    }};
参考: https://leetcode.com/discuss/99604/the-best-submission-ever-256ms-in-c-well-commented













0 0
原创粉丝点击