mirror of
				https://gitlab.com/game-loader/hugo.git
				synced 2025-10-30 06:08:54 +08:00 
			
		
		
		
	leetcode update
This commit is contained in:
		| @ -13899,3 +13899,207 @@ public: | ||||
| }; | ||||
|  | ||||
| ``` | ||||
|  | ||||
| ## day210 2024-09-24 | ||||
|  | ||||
| ### 3043. Find the Length of the Longest Common Prefix | ||||
|  | ||||
| You are given two arrays with positive integers arr1 and arr2. | ||||
|  | ||||
| A prefix of a positive integer is an integer formed by one or more of its digits, starting from its leftmost digit. For example, 123 is a prefix of the integer 12345, while 234 is not. | ||||
|  | ||||
| A common prefix of two integers a and b is an integer c, such that c is a prefix of both a and b. For example, 5655359 and 56554 have a common prefix 565 while 1223 and 43456 do not have a common prefix. | ||||
|  | ||||
| You need to find the length of the longest common prefix between all pairs of integers (x, y) such that x belongs to arr1 and y belongs to arr2. | ||||
|  | ||||
| Return the length of the longest common prefix among all pairs. If no common prefix exists among them, return 0. | ||||
|  | ||||
|  | ||||
|  | ||||
| ### 题解 | ||||
|  | ||||
| 题目中的数组要求求最长公共前缀,考虑到每个数组中的不同数字之间也可能存在公共前缀,为了避免对字符串进行重复遍历,可以使用字典树。字典树充分利用了数字每一位的信息,非常适用于类似本题目的求前缀等场景下,还有一道经典题目是求数组中任意两个数字的最大异或和,也可以使用字典树求解,利用异或运算异或两次后会回到数字本身的特性,用数字的二进制形式构造字典树,充分利用每个二进制位的信息,通过贪心尽量将每一位置为1,最终找到最大异或和,可参考[P4551 最长异或路径](https://www.luogu.com.cn/problem/P4551) | ||||
|  | ||||
| 本题在对两个数组构建好两棵字典树后,对字典树同时进行dfs,依次选取每一层中相同的字符对应的子节点进行遍历,直到在某一层无法找到共同字符为止。用一个变量保存遍历到的树的最大深度即为最长公共前缀的长度。 | ||||
|  | ||||
| ### 代码 | ||||
|  | ||||
| ```cpp | ||||
| #pragma GCC optimize("O3", "unroll-loops") | ||||
|  | ||||
| const int TREESIZE = 10; | ||||
|  | ||||
| struct TrieNode{ | ||||
|     TrieNode *children[TREESIZE]; | ||||
|     bool isEndOfWord; | ||||
|  | ||||
|     TrieNode(): isEndOfWord(false){ | ||||
|         for (int i = 0;i<TREESIZE;++i){ | ||||
|             children[i] = nullptr; | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| class Trie{ | ||||
|     public: | ||||
|     TrieNode *root; | ||||
|     Trie(){root = new TrieNode();} | ||||
|  | ||||
|     void insert(const string& word){ | ||||
|         TrieNode* node = root; | ||||
|         for(char c : word){ | ||||
|             if (node->children[c-'0'] == nullptr){ | ||||
|                 node->children[c-'0'] = new TrieNode(); | ||||
|             } | ||||
|             node = node->children[c-'0']; | ||||
|         } | ||||
|         node->isEndOfWord = true; | ||||
|     } | ||||
|  | ||||
|     ~Trie() { | ||||
|         function<void(TrieNode*)> deleteTrie = [&](TrieNode* node) { | ||||
|             if(node == nullptr) return; | ||||
|             for(int i = 0; i < TREESIZE; ++i){ | ||||
|                 if(node->children[i] != nullptr){ | ||||
|                     deleteTrie(node->children[i]); | ||||
|                 } | ||||
|             } | ||||
|             delete node; | ||||
|         }; | ||||
|         deleteTrie(root); | ||||
|     }; | ||||
|  | ||||
| }; | ||||
|  | ||||
| class Solution { | ||||
| public: | ||||
|     int longestCommonPrefix(vector<int>& arr1, vector<int>& arr2) { | ||||
|         ios::sync_with_stdio(false); | ||||
|         Trie *trie1 = new Trie(); | ||||
|         for (int num : arr1){ | ||||
|             string numstr = to_string(num); | ||||
|             trie1->insert(numstr); | ||||
|         } | ||||
|         Trie *trie2 = new Trie(); | ||||
|         for (int num : arr2){ | ||||
|             string numstr = to_string(num); | ||||
|             trie2->insert(numstr); | ||||
|         } | ||||
|         int result = 0; | ||||
|         dfs(trie1->root, trie2->root, 0, result); | ||||
|         return result; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     void dfs(TrieNode* root1,TrieNode* root2, int depth, int& result){ | ||||
|         result = max(result, depth); | ||||
|         for(int i=0;i<TREESIZE;i++){ | ||||
|             if (root1->children[i] != nullptr && root2->children[i] != nullptr){ | ||||
|                 cout<< i; | ||||
|                 dfs(root1->children[i],root2->children[i],depth+1,result); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }; | ||||
| ``` | ||||
|  | ||||
| ## day211 2024-09-25 | ||||
|  | ||||
| ### 2416. Sum of Prefix Scores of strings | ||||
|  | ||||
| You are given an array words of size n consisting of non-empty strings. | ||||
|  | ||||
| We define the score of a string word as the number of strings words[i] such that word is a prefix of words[i]. | ||||
|  | ||||
| For example, if words = ["a", "ab", "abc", "cab"], then the score of "ab" is 2, since "ab" is a prefix of both "ab" and "abc". | ||||
| Return an array answer of size n where answer[i] is the sum of scores of every non-empty prefix of words[i]. | ||||
|  | ||||
| Note that a string is considered as a prefix of itself. | ||||
|  | ||||
|  | ||||
|  | ||||
| ### 题解 | ||||
|  | ||||
| 本题是一道难题,但像这种要多次计算字符串前缀的问题我们已经熟悉了,为了避免重复遍历字符串可以使用字典树trie。在这个问题上思考一下为什么用字典树更好,如果我们用map将某个前缀作为key,其出现的次数作为value。这样对于有包含关系的前缀就会产生大量重复,同时没能充分利用前缀自身自带的字符的先后关系(字符串ab,a是在b前面且与b紧密相邻的,用字典树则将ab相邻和a在b前面这两种字符关系都表示了出来)。 | ||||
|  | ||||
| 熟悉字典树后,本题只需对每个字符串构建字典树,对字典树的节点做一些修改,节点中加入表示被访问到次数的count变量,无需记录节点是否为单词的结尾。构建好后对每个字符串,访问字典树,并将路径上所有节点的count相加即得最终的sum。 | ||||
|  | ||||
| ### 代码 | ||||
|  | ||||
| ```cpp | ||||
| const int ALPHABET_SIZE = 26; | ||||
|  | ||||
| struct TrieNode { | ||||
|     TrieNode* children[ALPHABET_SIZE]; | ||||
|     int count; | ||||
|  | ||||
|     TrieNode() : count(0) { | ||||
|         for(int i = 0; i < ALPHABET_SIZE; ++i){ | ||||
|             children[i] = nullptr; | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
|  | ||||
| class Trie { | ||||
| public: | ||||
|     TrieNode* root; | ||||
|  | ||||
|     Trie() { root = new TrieNode(); } | ||||
|  | ||||
|     void insert(const string &word) { | ||||
|         TrieNode* node = root; | ||||
|         for(char c : word){ | ||||
|             int index = c - 'a'; | ||||
|             if(index < 0 || index >= ALPHABET_SIZE){ | ||||
|                 continue; | ||||
|             } | ||||
|             if(node->children[index] == nullptr){ | ||||
|                 node->children[index] = new TrieNode(); | ||||
|             } | ||||
|             node = node->children[index]; | ||||
|             node->count++; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     int count(const string &word){ | ||||
|         int ret = 0; | ||||
|         TrieNode* node = root; | ||||
|         for(char c : word){ | ||||
|             int index = c - 'a'; | ||||
|             node = node->children[index]; | ||||
|             ret += node->count; | ||||
|         } | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     ~Trie() { | ||||
|         function<void(TrieNode*)> deleteTrie = [&](TrieNode* node) { | ||||
|             if(node == nullptr) return; | ||||
|             for(int i = 0; i < ALPHABET_SIZE; ++i){ | ||||
|                 if(node->children[i] != nullptr){ | ||||
|                     deleteTrie(node->children[i]); | ||||
|                 } | ||||
|             } | ||||
|             delete node; | ||||
|         }; | ||||
|         deleteTrie(root); | ||||
|     } | ||||
| }; | ||||
|  | ||||
|  | ||||
| class Solution { | ||||
| public: | ||||
|     vector<int> sumPrefixScores(vector<string>& words) { | ||||
|         Trie *trie = new Trie(); | ||||
|         for (string word : words){ | ||||
|             trie->insert(word); | ||||
|         } | ||||
|         vector<int> result; | ||||
|         for (string word : words){ | ||||
|             result.push_back(trie->count(word)); | ||||
|         } | ||||
|         return result; | ||||
|     } | ||||
| }; | ||||
| ``` | ||||
|  | ||||
		Reference in New Issue
	
	Block a user
	 gameloader
					gameloader