mirror of
https://gitlab.com/game-loader/hugo.git
synced 2025-04-20 05:52: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