LeetCode 剑指 Offer II 前缀树(上) 专题总结,java面试基础笔试题

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上Java开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip1024b (备注Java)
img

正文

Trie,又称前缀树或字典树,是一棵有根树,其每个节点包含以下字段:

  • 指向子节点的指针数组 children。对于本题而言,数组长度为 26,即小写英文字母的数量。此时 children[0] 对应小写字母 achildren[1] 对应小写字母 b,…,children[25] 对应小写字母 z
  • 布尔字段 isEnd,表示该节点是否为字符串的结尾。

我习惯用next替代children,因为比较好写吧,这题相当于介绍前缀树,所以代码也很简单,不懂的可以先百度前缀树,了解了再来看,无非就是把二叉树替换成26叉树,然后一个bool判断是否到达结尾,然后掌握插入和查询方法。

class Trie {

private:

// 前缀树, 相当于26叉树

vector<Trie*> next;

// 判断是否为单词终点

bool isWrod;

// 因为search,startsWith方法都需要查询,所以提取出查询方法

// 直接返回查询最后的点

Trie* searchPrefix(string prefix) {

Trie* node = this;

for(char ch : prefix) {

int index = ch - ‘a’;

if(node->next[index] != nullptr) {

node = node->next[index];

}else {

return nullptr;

}

}

return node;

}

public:

Trie():next(26),isWrod(false) {}

void insert(string word) {

int count = 0;

// 指向当前类,每个类都有26个分支

Trie* node = this;

for(char ch : word) {

int index = ch - ‘a’;

if(node->next[index] == nullptr) {

// 创建父类节点的index节点,此时index也有26个分支

node->next[index] = new Trie();

}

// 将父类指向index节点

node = node->next[index];

}

// 创建完当前node指向最后一个单词,设为单词终点

node->isWrod = true;

}

// 不为空 and 最后一个点的isWrod为true 代表word存在

bool search(string word) {

Trie* node = this->searchPrefix(word);

return node != nullptr && node->isWrod;

}

// 不为空即查到了前缀

bool startsWith(string prefix) {

Trie* node = this->searchPrefix(prefix);

return node != nullptr;

}

};

063. 替换单词

=========================================================================

题目:

在英语中,有一个叫做 词根(root) 的概念,它可以跟着其他一些词组成另一个较长的单词——我们称这个词为 继承词(successor)。例如,词根an,跟随着单词 other(其他),可以形成新的单词 another(另一个)。

现在,给定一个由许多词根组成的词典和一个句子,需要将句子中的所有继承词用词根替换掉。如果继承词有许多可以形成它的词根,则用最短的词根替换它。

需要输出替换之后的句子。

示例:

输入:dictionary = [“cat”,“bat”,“rat”], sentence = “the cattle was rattled by the battery”

输出:“the cat was rat by the bat”

提示:

  • 1 <= dictionary.length <= 1000

  • 1 <= dictionary[i].length <= 100

  • dictionary[i] 仅由小写字母组成。

  • 1 <= sentence.length <= 10^6

  • sentence 仅由小写字母和空格组成。

  • sentence 中单词的总量在范围 [1, 1000] 内。

  • sentence 中每个单词的长度在范围 [1, 1000] 内。

  • sentence 中单词之间由一个空格隔开。

  • sentence 没有前导或尾随空格。

思路:

  1. 将词根加入到前缀树中,insert方法跟上一题一样
  1. 分割字符串,将单词保存到数组中
  1. 处理字符串,就是找到词根就截取单词的词根部分,否则直接添加单词
`prefixLen`方法跟上题查询方法很像,本来查到结尾返回`true`,现在返回词根长度,查不到结尾就返回`0`,方便判断是否查到词根

class Trie {

private:

bool isWord;

vector<Trie*> next;

public:

Trie():next(26,nullptr),isWord(false){};

// 跟上一题一样

void insert(const string& word) {

Trie* node = this;

for(char ch : word) {

int index = ch - ‘a’;

if(node->next[index] == nullptr) {

node->next[index] = new Trie();

}

node = node->next[index];

}

node->isWord = true;

}

// 相对于上一题的search稍作修改

int prefixLen(const string& word) {

Trie* node = this;

// 返回前缀的长度

int len = 0;

for(char ch : word) {

int index = ch - ‘a’;

// 没有这个前缀

if(node->next[index] == nullptr) {

return 0;

}

node = node->next[index];

len++;

// 找到这个前缀并返回这个前缀的长度

if(node->isWord)

return len;

}

return 0;

}

};

class Solution {

public:

string replaceWords(vector& dictionary, string sentence) {

Trie* root = new Trie();

// 将词根加入前缀树

for(auto& word : dictionary) {

root->insert(word);

}

// 分割字符串

vector words{“”};

for(char ch : sentence) {

if(ch == ’ ') {

words.push_back(“”);

}else {

words.back().push_back(ch);

}

}

// 处理字符串

string res;

for(auto& word : words) {

int len = root->prefixLen(word);

// 没找到直接添加

if(len == 0){

res += word + " ";

}else {

// 找到前缀只添加前缀部分

res += word.substr(0, len) + " ";

}

}

res.pop_back();

return res;

}

};

064. 神奇的字典

==========================================================================

题目:

设计一个使用单词列表进行初始化的数据结构,单词列表中的单词 互不相同 。 如果给出一个单词,请判定能否只将这个单词中一个字母换成另一个字母,使得所形成的新单词存在于已构建的神奇字典中。

实现 MagicDictionary 类:

MagicDictionary() 初始化对象

void buildDict(String[] dictionary) 使用字符串数组 dictionary 设定该数据结构,dictionary 中的字符串互不相同

bool search(String searchWord) 给定一个字符串 searchWord ,判定能否只将字符串中 一个 字母换成另一个字母,使得所形成

示例:

输入

inputs = [“MagicDictionary”, “buildDict”, “search”, “search”, “search”, “search”]

inputs = [[], [[“hello”, “leetcode”]], [“hello”], [“hhllo”], [“hell”], [“leetcoded”]]

输出

[null, null, false, true, false, false]

解释

MagicDictionary magicDictionary = new MagicDictionary();

magicDictionary.buildDict([“hello”, “leetcode”]);

magicDictionary.search(“hello”); // 返回 False

magicDictionary.search(“hhllo”); // 将第二个 ‘h’ 替换为 ‘e’ 可以匹配 “hello” ,所以返回 True

magicDictionary.search(“hell”); // 返回 False

magicDictionary.search(“leetcoded”); // 返回 False

提示:

  • 1 <= dictionary.length <= 100

  • 1 <= dictionary[i].length <= 100

  • dictionary[i] 仅由小写英文字母组成

  • dictionary 中的所有字符串 互不相同

  • 1 <= searchWord.length <= 100

总结

其他的内容都可以按照路线图里面整理出来的知识点逐一去熟悉,学习,消化,不建议你去看书学习,最好是多看一些视频,把不懂地方反复看,学习了一节视频内容第二天一定要去复习,并总结成思维导图,形成树状知识网络结构,方便日后复习。

这里还有一份很不错的《Java基础核心总结笔记》,特意跟大家分享出来

目录:

部分内容截图:

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

习。

这里还有一份很不错的《Java基础核心总结笔记》,特意跟大家分享出来

目录:

[外链图片转存中…(img-SvTx30jw-1713637607919)]

部分内容截图:

[外链图片转存中…(img-Q0VbZHPW-1713637607920)]

[外链图片转存中…(img-4oycKwB4-1713637607921)]

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip1024b (备注Java)
[外链图片转存中…(img-CUFzzzx1-1713637607921)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值