Anagrams

来源:互联网 发布:铜板街软件 编辑:程序博客网 时间:2024/06/09 17:39


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();    }}



0 0