336. Palindrome Pairs
You are given a 0-indexed array of unique strings words.
A palindrome pair is a pair of integers (i, j) such that:
- 0 <= i, j < words.length,
- i != j, and
- words + words[j] (the concatenation of the two strings) is a palindrome
Return an array of all the palindrome pairs of words.
You must write an algorithm with O(sum of words.length) runtime complexity.
Example 1:
Input: words = [“abcd”,“dcba”,“lls”,“s”,“sssll”]
Output: [[0,1],[1,0],[3,2],[2,4]]
Explanation: The palindromes are [“abcddcba”,“dcbaabcd”,“slls”,“llssssll”]
Example 2:
Input: words = [“bat”,“tab”,“cat”]
Output: [[0,1],[1,0]]
Explanation: The palindromes are [“battab”,“tabbat”]
Example 3:
Input: words = [“a”,“”]
Output: [[0,1],[1,0]]
Explanation: The palindromes are [“a”,“a”]
Constraints:
- 1 <= words.length <= 5000
- 0 <= words.length <= 300
- words consists of lowercase English letters.
From: LeetCode
Link: 336. Palindrome Pairs
Solution:
Ideas:
1. Reversing and Hashing:
- The main idea is to use a hash map (or hash table) to store the reversed versions of each word. This allows us to quickly check if there is a word in the array that, when concatenated with another word, forms a palindrome.
2. Palindrome Checks:
- For each word, the code checks if any prefix or suffix forms a palindrome. If a suffix is a palindrome, it checks if the reverse of the prefix exists in the hash map. If a prefix is a palindrome, it checks if the reverse of the suffix exists in the hash map.
- By checking both the prefix and suffix, the code can detect potential palindrome pairs that can be formed by concatenating two different words in different orders.
3. Efficient String Handling:
- The code carefully manages memory, ensuring that strings are duplicated when stored in the hash map. This avoids issues with accessing freed memory, which was a problem in earlier versions of the code.
4. Use of a Hash Map:
- The hash map is used to store the reversed words along with their indices. This allows for O(1) average-time complexity lookups, which is crucial for achieving the required efficiency given the constraints.
Code:
- typedef struct {
- char* word;
- int index;
- } HashItem;
- typedef struct {
- HashItem* items;
- int size;
- } HashMap;
- int hashFunc(char* str, int size) {
- unsigned long hash = 5381;
- int c;
- while ((c = *str++)) {
- hash = ((hash << 5) + hash) + c;
- }
- return hash % size;
- }
- HashMap* createHashMap(int size) {
- HashMap* map = (HashMap*)malloc(sizeof(HashMap));
- map->items = (HashItem*)calloc(size, sizeof(HashItem));
- map->size = size;
- return map;
- }
- void insertHashMap(HashMap* map, char* word, int index) {
- int hash = hashFunc(word, map->size);
- while (map->items[hash].word != NULL) {
- hash = (hash + 1) % map->size;
- }
- map->items[hash].word = strdup(word); // Duplicate the word to avoid premature freeing
- map->items[hash].index = index;
- }
- int searchHashMap(HashMap* map, char* word) {
- int hash = hashFunc(word, map->size);
- while (map->items[hash].word != NULL) {
- if (strcmp(map->items[hash].word, word) == 0) {
- return map->items[hash].index;
- }
- hash = (hash + 1) % map->size;
- }
- return -1;
- }
- bool isPalindrome(char* word, int left, int right) {
- while (left < right) {
- if (word[left++] != word[right--]) {
- return false;
- }
- }
- return true;
- }
- char* reverseString(char* word) {
- int len = strlen(word);
- char* reversed = (char*)malloc((len + 1) * sizeof(char));
- for (int i = 0; i < len; i++) {
- reversed[i] = word[len - i - 1];
- }
- reversed[len] = '\0';
- return reversed;
- }
- int** palindromePairs(char** words, int wordsSize, int* returnSize, int** returnColumnSizes) {
- *returnSize = 0;
- int capacity = 10;
- int** result = (int**)malloc(capacity * sizeof(int*));
- *returnColumnSizes = (int*)malloc(capacity * sizeof(int));
- // Hash map to store reversed words and their indices
- int hashSize = 50000; // Increased size to reduce collisions
- HashMap* hashMap = createHashMap(hashSize);
- // Insert reversed words into the hash map
- for (int i = 0; i < wordsSize; i++) {
- char* reversed = reverseString(words[i]);
- insertHashMap(hashMap, reversed, i);
- free(reversed); // Free the reversed string after storing in the hash map
- }
- for (int i = 0; i < wordsSize; i++) {
- int len = strlen(words[i]);
- for (int j = 0; j <= len; j++) {
- // Check if the suffix forms a palindrome and if the reverse of the prefix exists in the map
- if (isPalindrome(words[i], j, len - 1)) {
- char* prefix = strndup(words[i], j);
- int index = searchHashMap(hashMap, prefix);
- if (index != -1 && index != i) {
- if (*returnSize == capacity) {
- capacity *= 2;
- result = (int**)realloc(result, capacity * sizeof(int*));
- *returnColumnSizes = (int*)realloc(*returnColumnSizes, capacity * sizeof(int));
- }
- result[*returnSize] = (int*)malloc(2 * sizeof(int));
- result[*returnSize][0] = i;
- result[*returnSize][1] = index;
- (*returnColumnSizes)[*returnSize] = 2;
- (*returnSize)++;
- }
- free(prefix); // Safe to free the prefix here
- }
- // Check if the prefix forms a palindrome and if the reverse of the suffix exists in the map
- if (j > 0 && isPalindrome(words[i], 0, j - 1)) {
- char* suffix = strdup(words[i] + j);
- int index = searchHashMap(hashMap, suffix);
- if (index != -1 && index != i) {
- if (*returnSize == capacity) {
- capacity *= 2;
- result = (int**)realloc(result, capacity * sizeof(int*));
- *returnColumnSizes = (int*)realloc(*returnColumnSizes, capacity * sizeof(int));
- }
- result[*returnSize] = (int*)malloc(2 * sizeof(int));
- result[*returnSize][0] = index;
- result[*returnSize][1] = i;
- (*returnColumnSizes)[*returnSize] = 2;
- (*returnSize)++;
- }
- free(suffix); // Safe to free the suffix here
- }
- }
- }
- // Free the hash table and the words stored in it
- for (int i = 0; i < hashSize; i++) {
- if (hashMap->items[i].word != NULL) {
- free(hashMap->items[i].word); // Free each stored word
- }
- }
- free(hashMap->items);
- free(hashMap);
- return result;
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |