题目分析:
给定一组唯一的单词,从中寻找所有的下标对(i,j),使得对应下标的单词拼接,即words[i] + words[j]是回文。
解题思路:
利用字典map保存单词与下标的键值对;
1)若当前的单词word本身是回文,且words中存在空串,则将空串下标bidx与idx加入答案;
2)若房钱单词的逆序串在words中,则将逆序串下标rids与idx加入答案;
3)将当前单词word拆分为左右两半left,right
3.1)若left为回文,并且right的逆序在words中,则将right的逆序串下标rridx与idx加入答案; 3.2)若right为回文,并且left的逆序串在words中,则将left的逆序串下标idx与rlidx加入答案。
实现程序
C++版本
// 方法1,借助set实现 class Solution { public: bool isValid(string temp, int left, int right) { while (left < right) { if (temp[left++] != temp[right--]) return false; } return true; } vector< vector<int> > palindromePairs(vector<string> & words) { vector< vector<int> > result; map<string, int> mp; set<int> s; // 遍历字符串数组,将所有的字符串保存在map中,同时记录其对应的位置,同时利用set保存其字符串的长度 for (int i = 0; i < words.size(); i++) { mp[words[i]] = i; s.insert(words[i].size()); } // 遍历字符创数组,将字符串进行逆转,查找其是否存在回文字符串 for (int i = 0; i < words.size(); i++) { string temp = words[i]; int len = temp.size(); reverse(temp.begin(), temp.end()); // 查找是否存在转置后的字符串,且其对应的位置不为temp的位置i,存在,则找到一对回文 if (mp.count(temp) && mp[temp] != i) { vector<int> tp; tp.push_back(i); tp.push_back(mp[temp]); result.push_back(tp); } set<int>::iterator it; // 分析其部分字符串中是否存在构成回文的字符串 for (it = s.begin(); it != s.find(len); it++) { int d = *it; if (isValid(temp, 0, len - d - 1) && mp.count(temp.substr(len - d))) { vector<int> tp; tp.push_back(i); tp.push_back(mp[temp.substr(len - d)]); result.push_back(tp); } if (isValid(temp, d, len - 1) && mp.count(temp.substr(0, d))) { vector<int> tp; tp.push_back(mp[temp.substr(0, d)]); tp.push_back(i); result.push_back(tp); } } } return result; } }; // 方法2 不借助set实现 class Solution { public: // 判断字符串是否是回文 bool isValid(string temp) { for (int i = 0; i < temp.size() / 2; i++) { if (temp[i] != temp[temp.size() - 1 - i]) return false; } return true; } vector< vector<int> > palindromePairs(vector<string> &words) { vector< vector<int> > result; map<string, int> mp; // 利用map存储每个单词,及其在字符串中的位置 for (int i = 0; i < words.size(); i++) { mp[words[i]] = i; } // 遍历所有单词 for (int i = 0; i < words.size(); i++) { int l = 0; // 记录左边移动字符数 int r = 0; // 记录右边移动字符数 while (l <= r) { string tp = words[i].substr(l, r - l); // 逆转子串 reverse(tp.begin(), tp.end()); // 判断是否存在逆串,且剩余字符串部分构成回文,先判断右边,在判断左边 if (mp.count(tp) && i != mp[tp] && isValid(words[i].substr(l == 0 ? r : 0, l == 0 ? words[i].size() - r : l))) { // 对应整个字符串构成回文情况 if (l == 0) { vector<int> t; t.push_back(i); t.push_back(mp[tp]); result.push_back(t); } // 对应字符串的子串构成回文 else { vector<int> t; t.push_back(mp[tp]); t.push_back(i); result.push_back(t); } } // 移动左或右标志 if (r < words.size()) r++; else l++; } } return result; } };
Java版本
boolean isValid(String temp){ for (int i = 0; i < temp.length() / 2; i++){ if (temp.charAt(i) != temp.charAt(temp.length() - 1 - i)) return false; } return true; } public List<List<Integer>> palindromePairs1(String[] words) { List<List<Integer>> result = new ArrayList<>(); Map<String, Integer> map = new HashMap<>(); for (int i = 0; i < words.length; i++){ map.put(words[i], i); } for (int i = 0; i < words.length; i++){ int l = 0; int r = 0; while (l <= r){ String substr = words[i].substring(l, r); Integer j = map.get(new StringBuilder(substr).reverse().toString()); // 处理右边 if (j != null && i != j && l == 0 && isValid(words[i].substring(r, words[i].length()))){ ArrayList<Integer> t = new ArrayList<Integer>(); t.add(i); t.add(j); result.add(t); } else { // 处理左边 if (j != null && i != j && l != 0 && isValid(words[i].substring(0, l))){ ArrayList<Integer> t = new ArrayList<Integer>(); t.add(j); t.add(i); result.add(t); } } // 移动左右标志 if (r == words[i].length()) l++; else r++; } } return result; }
参考文献
http://bookshadow.com/weblog/2016/03/10/leetcode-palindrome-pairs/
leetcode_336 Palindrome Pairs
最新推荐文章于 2022-12-03 23:59:55 发布