为了检查两个字符串是不是是字谜, hashfunction() 的逻辑应该是啥?

Posted

技术标签:

【中文标题】为了检查两个字符串是不是是字谜, hashfunction() 的逻辑应该是啥?【英文标题】:What should be the logic of hashfunction() in order to check that two strings are anagrams or not?为了检查两个字符串是否是字谜, hashfunction() 的逻辑应该是什么? 【发布时间】:2016-10-17 07:40:29 【问题描述】:

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

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;
    

【问题讨论】:

这里提示Output : [[1, 4], [2, 3]] 不是整数 【参考方案1】:

哦,天哪……这里有很多东西可以解释。区分大小写、语言环境、允许/列入黑名单的字符……有很多方法可以回答一般性问题。所以,首先,让我做出一些假设:

    大小写无关紧要。 (“Rat”是“Tar”的变位词,即使是大写字母。) 就字母表而言,语言环境是美式英语。 (来自 A-Z 的 26 个字母。将其与具有 28 个 IIRC 的西班牙语进行比较,其中 'll' 被认为是单个字母,可能是西班牙语字谜的考虑因素!) 在我们对字谜的定义中忽略了空格。 (“arthas menethil”是“头盔中的垃圾”的变位词,尽管空格的数量不同。) 空字符串(null,长度为 0,全为空格)的“哈希”(我更喜欢术语“摘要”,但名称就是名称)为 1。

如果您不喜欢这些假设中的任何一个,您可以随意修改它们。当然,这会导致以下算法略有不同,但它们是一套很好的指导方针,可以让一般算法相对容易理解和重构。

如果两个字符串完全由相同的字符集和相同数量的每个包含字符组成,则它们是字谜。 Java 中有很多可用的工具使这项任务变得相当简单。我们有 String 方法、Lists、Comparators、盒装原语和现有的 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 亿个唯一值,而且你可以扔给它的字符串要多得多。此方法可能会产生冲突并给您无意义的结果。如果这是个问题,您可能需要考虑改用 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;

【讨论】:

【参考方案2】:

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

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

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

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

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

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

【讨论】:

以上是关于为了检查两个字符串是不是是字谜, hashfunction() 的逻辑应该是啥?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查两个字符串是不是是字谜?

使用基本Java检查两个字符串是不是是彼此的字谜[重复]

检查两个字符串是不是是字谜的运行时间应该是多少

这是一个字谜程序,我正在检查两个相同长度的字符串是不是相互字谜

一种可能的算法来确定两个字符串是不是是彼此的字谜? [关闭]

使用 SET(C++) 检查两个给定字符串是不是为字谜时出现运行时错误