【算法题】兄弟单词

给定一个单词a,如果通过交换单词中字母的顺序可以得到另外的单词b,那么定义b是a的兄弟单词,例如单词army和mary互为兄弟单词。现在给定一个字典,用户输入一个单词,如何根据字典找出这个单词有哪些兄弟单词?要求时间和空间效率尽可能的高。【2012年百度实习生招聘笔试题】


  • 思路一:trie(字典)树

在字典树的前缀中再存储一个vector结构的容器:
struct word
{
vector brother; // 用于保存每个单词的兄弟单词
word *next[26]; // 26叉树,字典树中每个节点代表一个字符,并指向下一个字符
};

首先根据字典中的单词来建立字典树,建立的时候,需要稍微特殊处理一下,就是比如pots、stop和tops互为兄弟单词,那么在字典中按照首字母顺序的话,应该先遇到pots单词,那么我首先对其进行排序,结果是opts,那么字典树中就分别建立4个节点,分别为o->p->t->s,当然这个是不同层次的,在节点s处的vector容器brother中添加单词pots,遇到stop的时候,同样的方法,排序是opts,此时发现这4个节点已经建立了,那么只需要在第四个节点s处的vector容器brother中添加单词stop,tops单词的处理方法是同样的。
建立完字典树后,查询兄弟单词的效率就会很高了,比哈希的效率还要高;查到tops的兄弟的单词的时候,首先排序,那么就是opts,然后在字典树中查找opts,在s处将其vector容器brother中的的单词输出就是tops的所有兄弟单词。


  • 思路二:使用hash_map

首先定义一个key,使得兄弟单词有相同的key,不是兄弟的单词有不同的key。例如,将单词按字母从小到大重新排序后作为其key,比如bad的key为abd,good的key为dgoo。
使用链表将所有兄弟单词串在一起,hash_map的key为单词的key,value为链表的起始地址。
开始时,先遍历字典,将每个单词都按照key加入到对应的链表当中。当需要找兄弟单词时,只需求取这个单词的key,然后到hash_map中找到对应的链表即可。
这样创建hash_map时时间复杂度为O(n),查找兄弟单词时时间复杂度是O(1)。


#include <iostream>
#include <numeric>
#include<algorithm>
#include <string>
#include<hash_map>
using namespace std;

int BrotherWord(vector<string>& dic,string str)
{
    hash_map<string,vector<string>> hash;
    for (auto i = 0; i < dic.size();++i)
    {
        string s = dic[i];
        sort(s.begin(), s.end());
        hash[s].push_back(dic[i]);
    }
    sort(str.begin(), str.end());

    for (auto i = 0;i< hash[str].size(); ++i)
    {
        cout << hash[str][i]<<" ";
    }
    return 0;
}

int main()
{
    vector<string> dic;
    dic.push_back("hehao");
    dic.push_back("ehaoh");
    dic.push_back("haohe");
    dic.push_back("aoheh");
    dic.push_back("facri");
    dic.push_back("et");

    string str("oheha");

    BrotherWord(dic, str);

    return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值