hashfunction()的逻辑应该是什么,以便检查两个字符串是否是字谜?

时间:2016-06-16 00:54:39

标签: java hash hashmap anagram

我想编写一个函数,它将字符串作为参数并返回与该字符串对应的数字。

Integer hashfunction(String a)
{    
    //logic    
}

实际上我解决的问题如下:

给定一个字符串数组,返回作为字谜的所有字符串组。用表示原始列表中索引的整数列表表示组。

Input : cat dog god tca

Output : [[1, 4], [2, 3]]

这是我的实施: -

public class Solution {
    Integer hashfunction(String a)
    {
        int i=0;int ans=0;
        for(i=0;i<a.length();i++)
        {
            ans+=(int)(a.charAt(i));//Adding all ASCII values    
        }

        return new Integer(ans);
    }
    **Obviously this approach is incorrect**
    public ArrayList<ArrayList<Integer>> anagrams(final List<String> a) {
        int i=0;
        HashMap<String,Integer> hashtable=new HashMap<String,Integer>();
        ArrayList<Integer> mylist=new ArrayList<Integer>();
        ArrayList<ArrayList<Integer>> answer=new  ArrayList<ArrayList<Integer>>(); 
        if(a.size()==1)
        {
            mylist.add(new Integer(1));
            answer.add(mylist);
            return answer;
        }

        int j=1;
        for(i=0;i<a.size()-1;i++)
        {   

            hashtable.put(a.get(i),hashfunction(a.get(i)));
            for(j=i+1;j<a.size();j++)
            {

                if(hashtable.containsValue(hashfunction(a.get(j))))
                {
                    mylist.add(new Integer(i+1));
                    mylist.add(new Integer(j+1));
                    answer.add(mylist);
                    mylist.clear();


                }
            }
        }
        return answer;
    }
}

2 个答案:

答案 0 :(得分:0)

对于由相同字符组成的所有字符串,您需要一个相同的数字。

String.hashCode方法返回的数字对于由相同字符以相同顺序组成的所有字符串相同

如果您可以对所有单词进行一致排序(例如:按字母顺序排序),那么String.hashCode将为所有字谜返回相同的数字。

return String.valueOf(Arrays.sort(inputString.toCharArray())).hashCode();

注意:这适用于所有字谜词(没有假阴性),但它可能不适用于所有不是字谜的字(可能是误报)。这对于简短的单词来说是极不可能的,但是一旦你得到长达数百个字符的单词,你将开始遇到具有相同哈希码的多组字谜。

另请注意:这可以为您提供(问题标题)的答案,但对于您正在解决的问题,这还不够。您需要弄清楚如何将此数字与原始列表中的索引相关联。

答案 1 :(得分:0)

哦,男孩......这里有很多可以解释的东西。区分大小写,区域设置,允许的字符/列入黑名单......有很多方法可以回答一般问题。所以,首先,让我假设一些假设:

  1. 案件无关紧要。 (“鼠”是“焦油”的字谜,即使有大写字母。)
  2. 当涉及字母表时,Locale是美国英语。 (来自A-Z的26封信。比较西班牙语,其中有28个IIRC,其中'll'被认为是单个字母,是西班牙字谜的潜在考虑因素!)
  3. 在我们对anagram的定义中忽略了空格。 (“arthas menethil”是“头盔中的垃圾”的字谜,即使空格的数量不同。)
  4. 空字符串(null,0-length,all white-space)有一个“hash”(我更喜欢术语“digest”,但名称是名称)为1。
  5. 如果您不喜欢这些假设,可以根据需要进行修改。当然,这将导致以下算法略有不同,但它们是一组很好的指导方针,可以使通用算法相对容易理解和重构,如果你愿意的话。

    如果两个字符串完全由相同的字符集和每个包含字符的相同数字组成,则它们是字符串。 Java中有许多工具可以使这项任务变得非常简单。我们有...方法,列表,比较器,盒装基元和现有的hashCode方法......好吧,所有这些。我们将使用它们来制作我们的“哈希”方法。

    private static int hashString(String s) {
        if (s == null) return 0; // An empty/null string will return 0.
    
        List<Character> charList = new ArrayList<>(); 
        String lowercase = s.toLowerCase(); // This gets us around case sensitivity
    
        for (int i = 0; i < lowercase.length(); i++) {
            Character c = Character.valueOf(lowercase.charAt(i));
            if (Character.isWhitespace(c)) continue; // spaces don't count
            charList.add(c); // Note the character for future processing...
        }
    
        // Now we have a list of Characters... Sort it!
        Collections.sort(charList);
        return charList.hashCode(); // See contract of java.util.List#haschCode
    }
    

    瞧;你有一个方法可以消化一个字符串并产生一个表示它的整数,无论​​其中的字符顺序如何。你可以用这个来确定两个字符串是否是彼此的字谜...但我不会。您要求生成一个Integer的摘要函数,但请记住,在java中,Integer只是一个32位的值。这种方法只能生成大约42亿个唯一值,而且你可以投入超过42亿个字符串。这种方法可以产生碰撞并给你无意义的结果。如果这是一个问题,您可能需要考虑使用BigInteger。

    private static BigInteger hashString(String s) {
        BigInteger THIRTY_ONE = BigInteger.valueOf(31); // You should promote this to a class constant!
    
        if (s == null) return BigInteger.ONE; // An empty/null string will return 1.
    
        BigInteger r = BigInteger.ONE; // The value of r will be returned by this method
        List<Character> charList = new ArrayList<>(); 
        String lowercase = s.toLowerCase(); // This gets us around case sensitivity
    
        for (int i = 0; i < lowercase.length(); i++) {
            Character c = Character.valueOf(lowercase.charAt(i));
            if (Character.isWhitespace(c)) continue; // spaces don't count
            charList.add(c); // Note the character for future processing...
        }
    
        // Now we have a list of Characters... Sort it!
        Collections.sort(charList);
    
        // Calculate our bighash, similar to how java's List interface does.
        for (Character c : charList) {
            int charHash = c.hashCode();
            r=r.multiply(THIRTY_ONE).add(BigInteger.valueOf(charHash));
        }
    
        return r;
    }