Hard-题目47:336. Palindrome Pairs
2016-05-31 23:52
393 查看
题目原文:
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”]
题目大意:
给出一个单词列表,其中每个单词都是不同的。寻找所有的不同的索引对(I,j)使得words[i]+words[j]是回文串。
题目分析:
对于n个元素的单词列表,单词长度不超过k,很容易想到暴力解法,复杂度为O(kn^2),提交显然tle。
看到discuss中一位大神的解法,大致理解如下:
把每个字符串翻转后构建Trie树,trie树的每个节点增加两个信息:
int index,如果该点是单词,则记录在原列表的下标,如果不是,该值为-1
List list, 这个列表有点难理解,先摘抄原文如下:
Here I take another strategy: add an integer list to each TrieNode; the list will record the indices of all words satisfying the following two conditions: each word has a suffix represented by the current Trie node; the rest of the word forms a palindrome.
我是这样理解这段话的:list记录的是索引值,其中索引值对应的单词均以这个Trie节点为后缀(因为这棵trie树是反向构造的,所以这点代表的前缀对应为单词的后缀),并且该字符串去掉这一点对应串的后缀是个回文串。
构建完这样的trie树后,遍历单词列表,带上下标i放到trie树中搜索,因为trie树是反着存的,所以如果存在这样的回文串,必定能正向查找到一个节点j(例如列表里有abc和cba两个词,则trie树里存了abc这个节点),再看trie树中的abc节点的list,其中记录了所有以cba为结尾,剩下部分是回文串的下标,很显然这些字符串前面加上abc必是回文串!!!!!!!!
这里有两个trick,第一个是trie树的root节点是空,但列表中可能有空串,这样的情况下只需要看words[i]是不是回文即可。第二个trick是i本身若是回文串,则(i,i)也是回文的,但观察标程的输出发现i不能等于j(这个题目好像没有说清,不知道是不是我没理解好题意)。
源码:(language:java)
成绩:
63ms
Cmershen的碎碎念:
好题,很考验数据结构和算法设计能力。trie树是acm中的一种比较基础的数据结构,这题借助反向构建trie树来寻找回文串,应该在求职机试中会是难题,而且把如果数据出严一点,个人感觉放在acm竞赛里面也绝对不是一道水题。
Leetcode是面向面试的,如果哪位大仙能在面试的短时间和高心理压力下想得到这个算法,真的是大神了……
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”]
题目大意:
给出一个单词列表,其中每个单词都是不同的。寻找所有的不同的索引对(I,j)使得words[i]+words[j]是回文串。
题目分析:
对于n个元素的单词列表,单词长度不超过k,很容易想到暴力解法,复杂度为O(kn^2),提交显然tle。
看到discuss中一位大神的解法,大致理解如下:
把每个字符串翻转后构建Trie树,trie树的每个节点增加两个信息:
int index,如果该点是单词,则记录在原列表的下标,如果不是,该值为-1
List list, 这个列表有点难理解,先摘抄原文如下:
Here I take another strategy: add an integer list to each TrieNode; the list will record the indices of all words satisfying the following two conditions: each word has a suffix represented by the current Trie node; the rest of the word forms a palindrome.
我是这样理解这段话的:list记录的是索引值,其中索引值对应的单词均以这个Trie节点为后缀(因为这棵trie树是反向构造的,所以这点代表的前缀对应为单词的后缀),并且该字符串去掉这一点对应串的后缀是个回文串。
构建完这样的trie树后,遍历单词列表,带上下标i放到trie树中搜索,因为trie树是反着存的,所以如果存在这样的回文串,必定能正向查找到一个节点j(例如列表里有abc和cba两个词,则trie树里存了abc这个节点),再看trie树中的abc节点的list,其中记录了所有以cba为结尾,剩下部分是回文串的下标,很显然这些字符串前面加上abc必是回文串!!!!!!!!
这里有两个trick,第一个是trie树的root节点是空,但列表中可能有空串,这样的情况下只需要看words[i]是不是回文即可。第二个trick是i本身若是回文串,则(i,i)也是回文的,但观察标程的输出发现i不能等于j(这个题目好像没有说清,不知道是不是我没理解好题意)。
源码:(language:java)
public class Solution { class TrieNode { TrieNode[] next; int index; List<Integer> list; TrieNode() { next = new TrieNode[26]; index = -1; list = new ArrayList<>(); } } public List<List<Integer>> palindromePairs(String[] words) { List<List<Integer>> res = new ArrayList<>(); TrieNode root = new TrieNode(); for (int i = 0; i < words.length; i++) addWord(root, words[i], i); for (int i = 0; i < words.length; i++) search(words, i, root, res); return res; } private void addWord(TrieNode root, String word, int index) { for (int i = word.length() - 1; i >= 0; i--) { if (root.next[word.charAt(i) - 'a'] == null) root.next[word.charAt(i) - 'a'] = new TrieNode(); if (isPalindrome(word, 0, i)) root.list.add(index); root = root.next[word.charAt(i) - 'a']; } root.list.add(index); root.index = index; } private void search(String[] words, int i, TrieNode root, List<List<Integer>> list) { for (int j = 0; j < words[i].length(); j++) { if (root.index >= 0 && root.index != i && isPalindrome(words[i], j, words[i].length() - 1)) list.add(Arrays.asList(i, root.index)); root = root.next[words[i].charAt(j) - 'a']; if (root == null) return; } for (int j : root.list) { if (i != j) list.add(Arrays.asList(i, j)); } } private boolean isPalindrome(String word, int i, int j) { while (i < j) { if (word.charAt(i++) != word.charAt(j--)) return false; } return true; } }
成绩:
63ms
Cmershen的碎碎念:
好题,很考验数据结构和算法设计能力。trie树是acm中的一种比较基础的数据结构,这题借助反向构建trie树来寻找回文串,应该在求职机试中会是难题,而且把如果数据出严一点,个人感觉放在acm竞赛里面也绝对不是一道水题。
Leetcode是面向面试的,如果哪位大仙能在面试的短时间和高心理压力下想得到这个算法,真的是大神了……
相关文章推荐
- 区间动规--区分两道题--【cqoi】涂色&【cdoi】string painter
- 游戏编程中的人工智能技术-遗传算法入门(二)
- RAII(资源创建即释放)
- root.sh Fails to Start HAIP as Default Gateway is Configured for Private Network VLAN (文档 ID 1366211
- HDU 2653 - Waiting ten thousand years for Love
- LeetCode 70. Climbing Stairs
- 3.INSTALL_FAILED_UPDATE_INCOMPATIBLE
- main Runloop
- 游戏编程中的人工智能技术-第三章:遗传算法入门(一)
- Seaborn-PairGrid
- grails指定端口运行工程
- [LeetCode]problem 70. Climbing Stairs
- HDOJ--Fibonacci Again
- Middle-题目122:220. Contains Duplicate III
- 1079. Total Sales of Supply Chain (25)
- leetcode 217. Contains Duplicate
- 1282 - Leading and Trailing ---LightOj1282(快速幂 + 数学)
- 【BZOJ1664】[Usaco2006 Open]County Fair Events 参加节日庆祝【线段覆盖】【贪心】
- Palindrome Pairs
- poj 3378 Crazy Thairs