• 寻找兄弟单词(2012.5.6百度实习)


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

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

    解法二:同样使用hash_map和链表
    (1)将每一个字母对应一个质数,然后让对应的质数相乘,将得到的值进行hash,这样兄弟单词的值就是一样的了,并且不同单词的质数相乘积肯定不同。
    (2)使用链表将所有兄弟单词串在一起,hash_map的key为单词的质数相乘积,value为链表的起始地址。
    (3)对于用户输入的单词进行计算,然后查找hash,将链表遍历输出就得到所有兄弟单词。
    这样创建hash_map时时间复杂度为O(n),查找兄弟单词时时间复杂度是O(1)。

    如果是海量词典的话,可以用B+树。。。。。

    注:上述两种方法是比较高效的算法,一下介绍一种普通方法:

    解法三:全排列,然后依次比较
    看到这个题目后,直觉是可能是这样的:求出输入单词的全部变换(假如单词的长度是n,则其全部变换有n!个。如果有相同的字母就不是n!了),求出单词的变换后,判断每个变换是否在字典中。例如对于输入abc,则其变换有3!=6种:abc、acb、bca、bac、cab、cba。然后在依次判断这6个单词(当然这里不是单词了,而是字符串)是否在字典中,如果在字典中则记录下来。
    很明显这种思想的复杂度是比较高的,因为对于n稍微大点的话,n!是一个很可怕的递增过程,因此这个方法是不太可取的。
    以下是全排列代码:

    /**
         * @param src
         * @param start 起始位置索引
         * @param end  结束位置索引
         */
       public static void perm(String[] src,int start,int end){
            if(start==end){//当只要求对数组中一个字母进行全排列时,只要按该数组输出即可
                for(int i=0;i<=end;i++){
                    System.out.print(src[i]);
                }
                System.out.println();
            }
            else{//多个字母全排列
                for(int i=start;i<=end;i++){
                    String temp=src[start];//交换数组第一个元素与后续的元素
                    src[start]=src[i];
                    src[i]=temp;
                    perm(src,start+1,end);//后续元素递归全排列
                    temp=src[start];//将交换后的数组还原
                    src[start]=src[i];
                    src[i]=temp;
                }
            }
        }

    将字典中的和‘比较单词’首字母相同的单词取出存放到一个数组中,将每一个组合和字典中的单词比较。首先比较单词长度,长度相同,则继续比较;否则,比较下一个单词。算法如下:

    /**
         * @param src 字典中的单词
         * @param des 要比较的单词,因为要做大量比较,所以转化为字符数组
         * @return
         */
        public static boolean compare(String src,String[] des){
            int len = src.length();
            if(len != des.length){//如果长度不相等,肯定不是兄弟单词,则无需比较
                return false;
            }
            int i = 1;//i等于1是因为首字符已经相同,无需比较
            while(i<len){
                if(des[i].equals(String.valueOf(src.charAt(i)))){
                    i++;
                    continue;
                }
                return false;
            }
            return true;
        }
  • 相关阅读:
    Android学习记录(4)—在java中学习多线程下载的基本原理和基本用法①
    Android之Notification的多种用法
    通过学习制作长微博工具来了解水印的制作,及EditText中的内容在图片中换行显示
    通过短信窃听器来讲解内容提供者,内容观察者,以及无界面后台运行服务,开机启动和杀死服务后重新启动
    通过重写ViewGroup学习onMeasure()和onLayout()方法
    Android学习记录(3)—Android中ContentProvider的基本原理学习总结
    Android学习记录(2)—Android中数据库的常见操作
    Android学习记录(1)—Android中XML文件的序列化生成与解析
    Android之判断设备网络连接状态,并判断连接方式
    Android获取SD卡总容量,可用大小,机身内存总容量及可用大小的系统方法
  • 原文地址:https://www.cnblogs.com/sooner/p/3094208.html
Copyright © 2020-2023  润新知