2022/03/27
题目一:字典序的第k小数字
字典树的思想 一个有9棵树的森林 每个结点包含10棵子树 关键在于求出每个子树中共包含多少个结点(包含根节点本身)
假设当前要求第k小结点 此时求出结点root的第一个树中结点个数为i个,curr来表示当前所在结点所对应的数字,最一开始的时候为1,即curr=1;
假设i<=step(step=k-1 减1是因为要减去当前结点本身)
那么说明走掉i步之后 还没有到达第k小的数字 所以肯定不在第1个树中 则向后查找i个后来到了curr相邻的右边的兄弟结点 即来到了第2棵树 此时step-step-i ,curr=curr+1;
如果i>step
那么则说明第k小的数字 在curr的子树之中,则应进一步缩小范围,向下查找
此时curr=curr*10,同时向下走一步后step=step-1;
class Solution {
public:
int getSteps(int curr,long n) //计算当前结点有多少个子节点
{
long first=curr,end=curr,ans=0;
while(first<=n)
{
ans += min(end, n) - first + 1;
first=first*10;
end=end*10+9;
}
return ans;
}
int findKthNumber(int n, int k) {
int curr = 1 , step = k-1;
long long e;
while(step>0)
{
e=getSteps(curr,n);
cout<<e<<endl;
if(e>step)
{
curr=curr*10;
step--;
}
else
{
curr=curr+1;
step=step-e;
}
}
return curr;
}
};
题目二:词典中最长的单词
思路:root作为根节点 每个根节点包含26个子节点 初始化全都为nullptr 然后插入单词 在插入过程中 如果需要将对应位置的nullptr进行赋值 同时用isend来标记从根节点到该节点是否存在一个单词 isend=true表示存在对应单词 否则则表示根节点到该节点只是一个前缀
class tree{
public:
//构造函数
tree(){
children = vector<tree *>(26,nullptr);
end=false;
}
//插入某个字母
bool insert(string word)
{
tree * node=this;
for(int i=0;i<word.length();i++)
{
int pos=word[i]-'a';
if(node->children[pos]==nullptr)
node->children[pos]=new tree();
node=node->children[pos];
}
node->end=true;
return true;
}
//查找某个字符串是不是在字典树中 保证每一步中经过的结点对应的end都是true;
bool search(string word)
{
tree * node=this;
for(int i=0;i<word.length();i++)
{
int pos=word[i]-'a';
if(node->children[pos]==nullptr || node->children[pos]->end==false)
return false;
node=node->children[pos];
}
return true;
}
private:
vector<tree *> children ;
bool end;
};
class Solution {
public:
string longestWord(vector<string>& words) {
string ans="";
tree root;
for(int i=0;i<words.size();i++)
{
root.insert(words[i]);
}
for(int i=0;i<words.size();i++)
{
if(root.search(words[i]))
{
if(words[i].length()>ans.length() || (words[i].length()==ans.length() && words[i]<ans ))
ans=words[i];
}
}
return ans;
}
};
题目三:
持续更新…