Anagrams


Given an array of strings, return all groups of strings that are anagrams.

Note: All inputs will be in lower-case.

Have you been asked this question in an interview? 
开始没读懂题目意思,别人解释:

Given an array of strings, return all groups of strings that are anagrams.

Note: All inputs will be in lower-case.

For example:

Input:  ["tea","and","ate","eat","den"]

Output:   ["tea","ate","eat"]

Interface: vector<string>anagrams(vector<string>&strs);

A:

首先简单介绍一下Anagram(回文构词法)。Anagrams是指由颠倒字母顺序组成的单词,比如“dormitory”颠倒字母顺序会变成“dirty room”,“tea”会变成“eat”。

回文构词法有一个特点:单词里的字母的种类和数目没有改变,只是改变了字母的排列顺序。


看了别人这些方法 无论怎么做,都是为了构建hashmap 的key 

假设有n个string,string 最长长度为k

如果用按照字母排序,时间复杂度o(nklogk)

另外两种方法,o(nk)

这道题目除了思路,还要注意对于iterator, collection, map 等 他们的相关方法使用

public class Solution {
    public List<String> anagrams(String[] strs) {
        if (strs == null) {
            return null;
        }
        List<String> result = new ArrayList<String>();
        HashMap<String, ArrayList<String>> hm = new HashMap<String, ArrayList<String>>();
        for (int i = 0; i < strs.length; i++) {
            if(!hm.containsKey(sortLetter(strs[i]))) {
                hm.put(sortLetter(strs[i]), new ArrayList<String>());
            }
            hm.get(sortLetter(strs[i])).add(strs[i]);
        }
        // hm.values() 返回的是 a collection of the values in this map
        // 对于collection 结构的数据,都有iterator() 方法
        Iterator iter = hm.values().iterator();
        while(iter.hasNext()) {
            ArrayList<String> item = (ArrayList<String>)iter.next();  
            if(item.size()>1) { 
                result.addAll(item);  
            }
        }
        /* hm.values() 返回的是实现了collection 的一种数据类型叫 Values, 不可以被转化为arraylist
        ArrayList<ArrayList<String>> aa = (ArrayList<ArrayList<String>>)hm.values();
        for (int i = 0; i < aa.size(); i++) {
            if (aa.get(i).size() > 1) {
                result.addAll(aa.get(i));
            }
        }
        */
        return result;
    }
    String sortLetter(String s) {
        //不要忘记考虑空字符串
        if (s == null || s.length() == 0) {
            return s;
        }
        char[] charArr = s.toCharArray();
        Arrays.sort(charArr);
        String str = new String(charArr);//用到String 的构造函数
        return str;
    }

}


网上看到另外一人解法 http://huntfor.iteye.com/blog/2077967:

public List<String> anagrams(String[] strs) {  
        List<String> result = new ArrayList<String>();   
        Map<String,List<String>> map = new HashMap<String,List<String>>();  
        if(strs == null || strs.length == 1){  
            return result;  
        }  
        for(String s : strs){  
            String seq = getSequence(s);  
            if(map.containsKey(seq)){  
                map.get(seq).add(s);  
            }else{  
                List<String> list = new ArrayList<String>();  
                list.add(s);  
                map.put(seq, list);  
            }  
        }  
        for(Map.Entry<String, List<String>> entry : map.entrySet()){  
            if(entry.getValue().size() > 1){  
                for(String s : entry.getValue()){  
                    result.add(s);  
                }  
            }  
        }  
        return result;  
    }     
    private String getSequence(String s){  
        if("".equals(s)){  
            return "";  
        }  
        int[] hash = new int[256];  
        StringBuilder sb = new StringBuilder();  
        for(int i = 0; i < s.length(); i++){  
            hash[s.charAt(i)]++;  
        }  
        for(int i = 97; i < 123; i++){  
            if(hash[i] != 0){  
                sb.append((char)i).append(hash[i]);  
            }  
        }  
        return sb.toString();  
    }  

第二次写出错的地方:

while (iter.hasNext()) {
            ArrayList<String> items = (ArrayList<String>)iter.next();
            //cannot addAll(iter.next()) directely
            //res.addAll(iter.next());
            //test case:[""], the output should be [ ]
            if (items.size() > 1) {
                res.addAll(items);
            }
        }



/**
 * Copyright: NineChapter
 * - Algorithm Course, Mock Interview, Interview Questions
 * - More details on: http://www.ninechapter.com/
 */

public class Solution {
    private int getHash(int[] count) {
        int hash = 0;
        int a = 378551;
        int b = 63689;
        for (int num : count) {
            hash = hash * a + num;
            a = a * b;
        }
        return hash;
    }
    
    public ArrayList<String> anagrams(String[] strs) {
        ArrayList<String> result = new ArrayList<String>();
        HashMap<Integer, ArrayList<String>> map = new HashMap<Integer, ArrayList<String>>();

        for (String str : strs) {
            int[] count = new int[26];
            for (int i = 0; i < str.length(); i++) {
                count[str.charAt(i) - 'a']++;
            }

            int hash = getHash(count);
            if (!map.containsKey(hash)) {
                map.put(hash, new ArrayList<String>());
            }

            map.get(hash).add(str);
        }

        for (ArrayList<String> tmp : map.values()) {
            if (tmp.size() > 1) {
                result.addAll(tmp);
            }
        }

        return result;
    }
}


方法挺简单就是建立一个int数组来记录一个字符在一个string里面出现的次数 然后对比int[]数组是否相等就好。 不过这里有几个注意点和小技巧。 int数组可以只设为26而不是256, 然后数组这样的Object类型没法直接用来做key首先要写一个函数把它的hash值转换为基本数据类型。 然后就是要存arraylist作为value,因为如果直接把string用来做value最后会少加一次anagrams进rs。用arraylist存只要size大于1 就可以addall.


public class Solution {
    public List<String> anagrams(String[] strs) {
        List<String> rs = new ArrayList<String>();
        if (strs.length < 2) {
            return rs;
        }
        HashMap<String, ArrayList<String>> hm = new HashMap<String, ArrayList<String>>();
        for (String i : strs) {
            int len = i.length();
            int[] temp = new int[26];
            for (int j = 0; j < len; j++) {
                temp[i.charAt(j) - 'a']++;
            }
            String t = getString(temp);
            if (!hm.containsKey(t)) {
                hm.put(t, new ArrayList<String>());
            }
            hm.get(t).add(i);
        }
        for (ArrayList<String> i : hm.values()) {
            if (i.size() > 1) {
                rs.addAll(i);
            }
        }
        return rs;
    }
    
    private String getString(int[] a) {
        StringBuilder sb = new StringBuilder();
        for (int i : a) {
            sb.append(i);
        }
        return sb.toString();
    }
}



基于Spring Boot搭建的一个多功能在线学习系统的实现细节。系统分为管理员和用户两个主要模块。管理员负责视频、文件和文章资料的管理以及系统运营维护;用户则可以进行视频播放、资料下载、参与学习论坛并享受个性化学习服务。文中重点探讨了文件下载的安全性和性能优化(如使用Resource对象避免内存溢出),积分排行榜的高效实现(采用Redis Sorted Set结构),敏感词过滤机制(利用DFA算法构建内存过滤树)以及视频播放的浏览器兼容性解决方案(通过FFmpeg调整MOOV原子位置)。此外,还提到了权限管理方面自定义动态加载器的应用,提高了系统的灵活性和易用性。 适合人群:对Spring Boot有一定了解,希望深入理解其实际应用的技术人员,尤其是从事在线教育平台开发的相关从业者。 使用场景及目标:适用于需要快速搭建稳定高效的在线学习平台的企业或团队。目标在于提供一套完整的解决方案,涵盖从资源管理到用户体验优化等多个方面,帮助开发者更好地理解和掌握Spring Boot框架的实际运用技巧。 其他说明:文中不仅提供了具体的代码示例和技术思路,还分享了许多实践经验教训,对于提高项目质量有着重要的指导意义。同时强调了安全性、性能优化等方面的重要性,确保系统能够应对大规模用户的并发访问需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值