[经典面试题][百度]寻找兄弟单词

简介:

题目

一个单词单词字母交换,可得另一个单词,如army->mary,成为兄弟单词。提供一个单词,在字典中找到它的兄弟。描述数据结构和查询过程。

思路一
兄弟单词必须满足字符相同,相同字符个数也必须相同。基于这点用Hash实现:
(1)申请一个int数组 count[26]用来统计每个字符出现的次数。
(2)扫描字典中的单词,只考虑长度和给出单词长度一样大小的单词(长度不同肯定不是兄弟单词),用broCount[26]来统计单词中每个字符出现的次数。
(3)如果count和broCount一样,表示是兄弟单词否则不是。

代码一

    /*---------------------------------------------
    *   日期:2015-02-22
    *   作者:SJF0115
    *   题目: 兄弟单词
    *   来源:百度
    *   博客:
    -----------------------------------------------*/
    #include <iostream>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    using namespace std;

    class Solution {
    public:
        // dic字典集合 word查找单词
        vector<string> BrotherWord(vector<string> dic,string word){
            int count[26];
            vector<string> brother;
            // 初始化
            memset(count,0,sizeof(count));
            int wordSize = word.size();
            int dicSize = dic.size();
            // 统计字符以及个数
            for(int i = 0;i < wordSize;++i){
                ++count[word[i]-'a'];
            }//for
            // 遍历字典
            for(int i = 0;i < dicSize;++i){
                if(IsBrother(word,count,dic[i])){
                    brother.push_back(dic[i]);
                }//if
            }//for
            return brother;
        }
    private:
        bool IsBrother(string word,int count[],string broWord){
            int size = broWord.size();
            int wordSize = word.size();
            // 长度不一样肯定不是兄弟单词
            if(size != wordSize){
                return false;
            }//if
            // 统计字符及个数
            int broCount[26];
            memset(broCount,0,sizeof(broCount));
            for(int i = 0;i < size;++i){
                ++broCount[broWord[i]-'a'];
            }//for
            // 只有字符一样,字符个数一样才是兄弟单词
            int k;
            for(k = 0;k < 26;++k){
                // 不是兄弟单词
                if(count[k] != broCount[k]){
                    break;
                }//if
            }//for
            if(k == 26){
                return true;
            }//if
            return false;
        }
    };


    int main() {
        Solution solution;
        vector<string> dic = {"mary","many","book","army","mood","man","doom","mod"};
        string word("mary");
        vector<string> result = solution.BrotherWord(dic,word);
        for(int i = 0;i < result.size();++i){
            cout<<result[i]<<" ";
        }//for
        cout<<endl;
    }

思路二:

在字典树的中再存储一个vector结构的容器来储存兄弟单词。

struct TrieNode{
        TrieNode *next[MAX];
        vector<string> brother;
        TrieNode(){
            for(int i = 0;i < MAX;++i){
                next[i] = NULL;
            }//for
        }
    };

字典树的建立是在预处理阶段完成的,首先根据字典中的单词来建立字典树,建立的时候,需要稍微特殊处理一下,就是比如mary、army互为兄弟单词,如果先插入单词mary,首先对其进行排序,结果是amry,那么字典树中就分别建立4个节点,分别为a->m->r->y,在节点y处的vector容器brother中添加单词mary,插入army的时候,同样的原理,先排序,再插入,此时发现这4个节点已经建立了,那么只需要在第四个节点y处的vector容器brother中添加单词army。
这样建立完字典树后,查询兄弟单词的效率就会很高了,比哈希的效率还要高;查询army的兄弟单词时,先排序(amry),然后在字典树中查找amry,在y处vector容器brother中的的单词就是所有兄弟单词。

代码二

    /*---------------------------------------------
    *   日期:2015-02-23
    *   作者:SJF0115
    *   题目: 兄弟单词
    *   来源:百度
    *   博客:
    -----------------------------------------------*/
    #include <iostream>
    #include <vector>
    #include <cstring>
    #include <algorithm>
    using namespace std;

    #define MAX 26

    struct TrieNode{
        TrieNode *next[MAX];
        vector<string> brother;
        TrieNode(){
            for(int i = 0;i < MAX;++i){
                next[i] = NULL;
            }//for
        }
    };
    // 插入
    void Insert(TrieNode* &root,string str){
        int size = str.size();
        TrieNode *p = root;
        string tmp = str;
        // 排序
        sort(tmp.begin(),tmp.end());
        // 插入
        int val;
        for(int i = 0;i < size;++i){
            val = tmp[i] - 'a';
            if(p->next[val] == NULL){
                p->next[val] = new TrieNode();
            }//if
            p = p->next[val];
        }//for
        p->brother.push_back(str);
    }
    // 预处理
    void Init(vector<string> dic,TrieNode* &root){
        int dicSize = dic.size();
        if(dicSize <= 0){
            return;
        }//if
        // 创建字典树
        for(int i = 0;i < dicSize;++i){
            Insert(root,dic[i]);
        }//for
    }
    // 打印字典
    void PrintDic(TrieNode* root){
        if(root == NULL){
            return;
        }//if
        if(root->brother.size() > 0){
            for(int i = 0; i <  root->brother.size();++i){
                cout<<root->brother[i]<<" ";
            }//for
            cout<<endl;
        }//if
        for(int i = 0;i < 26;++i){
            PrintDic(root->next[i]);
        }//for
    }
    // 兄弟单词
    vector<string> BrotherWord(TrieNode *root,string word){
        int size = word.size();
        vector<string> brother;
        if(root == NULL || size <= 0){
            return brother;
        }//if
        // 排序
        sort(word.begin(),word.end());
        TrieNode *p = root;
        int val;
        for(int i = 0;i < size;++i){
            val = word[i] - 'a';
            if(p->next[val] == NULL){
                return brother;
            }//if
            p = p->next[val];
        }//for
        return p->brother;
    }


    int main() {
        vector<string> dic = {"mary","many","book","army","mood","mray","man","doom","mod"};
        string word("mod");
        TrieNode *root = new TrieNode();
        // 预处理 创建字典树
        Init(dic,root);
        // 查询兄弟单词
        vector<string> result = BrotherWord(root,word);
        if(result.size() <= 0){
            cout<<"单词["<<word<<"]没有兄弟单词"<<endl;
        }//if
        else{
            cout<<"单词["<<word<<"]有兄弟单词:";
            for(int i = 0;i < result.size();++i){
                cout<<result[i]<<" ";
            }//for
            cout<<endl;
        }
    }

引用:

如何找出字典中的兄弟单词
[算法系列之二十]字典树(Trie)
寻找兄弟单词(2012.5.6百度实习)

目录
相关文章
|
11月前
|
算法 前端开发 Java
数据结构与算法学习四:单链表面试题,新浪、腾讯【有难度】、百度面试题
这篇文章总结了单链表的常见面试题,并提供了详细的问题分析、思路分析以及Java代码实现,包括求单链表中有效节点的个数、查找单链表中的倒数第k个节点、单链表的反转以及从尾到头打印单链表等题目。
122 1
数据结构与算法学习四:单链表面试题,新浪、腾讯【有难度】、百度面试题
|
存储 缓存 安全
兄弟面试了百度,面试题分享一波
兄弟面试了百度,面试题分享一波
141 0
|
机器学习/深度学习 自然语言处理 算法
百度2024校招机器学习、数据挖掘、自然语言处理方向面试经历
百度2024校招机器学习、数据挖掘、自然语言处理方向面试经历
366 2
面试美团、头条、百度、京东,一名3年Java开发经验的面试总结
毕业转行做开发3年以来, 学到了很多, 加上自己的兴趣爱好, 个人认为已经成为了一个合格的程序员. 与刚开始找工作面试相同的是都会问一些相同的问题, 不同的是现在面试官会更注重为什么, 也就是说注重深度而非广度. 3年, 5年, 10年分别是个人从事技术方面职业规划中的一个坎, 3年大部分时间应对了业务逻辑, 培养良好的规范和思想, 基础知识还是欠缺.
|
存储 前端开发 JavaScript
【面试题】(简单粗暴点)百度一面,直接问痛我
【面试题】(简单粗暴点)百度一面,直接问痛我
121 0
|
Linux 应用服务中间件 数据库
Linux 面试题-(腾讯,百度,美团,滴滴)
Linux 面试题-(腾讯,百度,美团,滴滴)
133 0
|
存储 SQL 设计模式
C++面试题,阿里、百度、腾讯、华为、小米100道C++面试题目及答案
C++面试题,阿里、百度、腾讯、华为、小米100道C++面试题目及答案
1124 0
|
存储 安全 前端开发
C++面试题,阿里、百度、腾讯、华为、小米100道C++面试题目及答案(下)
C++面试题,阿里、百度、腾讯、华为、小米100道C++面试题目及答案
|
JavaScript 开发工具 git
大厂面试-百度
大厂面经-百度
151 0
一道网红面试题(腾讯、百度面试中都出现过)
在腾讯和百度的面试中,出现了这样一道面试题,,被大家亲切的称呼为网红面试题,这道面试题就是。['1', '2', '3'].map(parseInt)的输出结果是什么?['1', '2', '3'].fliter(parseInt)的输出结果是什么? 这个面试题,面试官可能不仅仅需要你说出他的结果,还需要你知道为什么会出现这样的结果。
219 0