mirror of
https://gitlab.com/game-loader/hugo.git
synced 2025-04-19 21:42:07 +08:00
leetcode update
This commit is contained in:
parent
0149d9ca67
commit
57ebd283c8
@ -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;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
Loading…
Reference in New Issue
Block a user