简体   繁体   English

简单的 Map 中键的长度如何重新排列?

[英]How is the length of keys rearranged in a simple Map?

We are given a sentence text (A sentence is a string of space-separated words) in the following format:我们得到一个句子文本(一个句子是一串以空格分隔的单词),格式如下:

First letter is in upper case.第一个字母大写。 Each word in text are separated by a single space.文本中的每个单词都由一个空格分隔。 Our task is to rearrange the words in text such that all words are rearranged in an increasing order of their lengths.我们的任务是重新排列文本中的单词,使所有单词都按照长度递增的顺序重新排列。 If two words have the same length, we arrange them in their original order.如果两个词的长度相同,我们按照它们原来的顺序排列它们。

Example:

Input: text = "Keep calm and code on"
Output: "On and keep calm code"
Explanation: Output is ordered as follows:
"On" 2 letters.
"and" 3 letters.
"keep" 4 letters in case of tie order by position in the original text.
"calm" 4 letters.
"code" 4 letters.

The solution is:解决方案是:

class Solution {
    
    public String arrangeWords(String inputText) {
        String text = inputText.toLowerCase();
        String[] allWords = text.split("\\s+");

        Map<Integer, List<String>> lengthToWordsMap = new HashMap<>();

        for (int i = 0; i < allWords.length; i++) {
            lengthToWordsMap.computeIfAbsent(allWords[i].length(), k -> new ArrayList<>());
            lengthToWordsMap.get(allWords[i].length()).add(allWords[i]);
        }

        StringBuilder answerStringBuilder = new StringBuilder();

        for (int length : lengthToWordsMap.keySet()) {
            for (String word : lengthToWordsMap.get(length)) {
                answerStringBuilder.append(answerStringBuilder.length() == 0 ? "" : " ").append(word);
            }
        }

        String firstLetterInUppercase = answerStringBuilder.toString().substring(0, 1).toUpperCase();
        String restOfSentenceInLowercase = answerStringBuilder.toString().substring(1);
        
        String answer = firstLetterInUppercase + restOfSentenceInLowercase;
        
        return answer;
    }
}

I understand that after splitting the text and storing it in a String array, we are using a HashMap to store the length of words as the key and the words of that length as the length's values.我知道在拆分文本并将其存储在字符串数组中之后,我们使用 HashMap 将单词的长度存储为键,并将该长度的单词存储为长度的值。 But keys are not sorted in HashMaps so the length is not sorted either.但是键在 HashMaps 中没有排序,所以长度也没有排序。 So, after appending the words of each key (length of each word) to "sb", how are we ensuring that the words are rearranged in increasing order of their length?那么,在将每个键的单词(每个单词的长度)附加到“sb”之后,我们如何确保单词按长度递增的顺序重新排列?

Edit:编辑:

Okay, this is not my code.好吧,这不是我的代码。 This was one of the solutions posted on the discussion board.这是发布在讨论板上的解决方案之一。 This question is posted on Leetcode and the link to the question is here .这个问题发布在 Leetcode 上,问题的链接在这里

This solution passes all the 75 test cases too so I don't think this is working just by chance.这个解决方案也通过了所有 75 个测试用例,所以我认为这不是偶然的。

HashMap stores keys in a map by first converting the key to an integer called the hash value. HashMap将密钥存储在 map 中,首先将密钥转换为 integer,称为 Z0800FC5772894C34E90BZ28 值。 This is done by calling the hashCode() method on the object.这是通过调用 object 上的hashCode()方法来完成的。 Then finding a bin in the hash table depending on this hash value.然后根据这个 hash 值在 hash 表中找到一个 bin。

If you are using Oracle or OpenJDK, chances are that hashCode() of integer returns the int itself (because the hash value is also just an int ):如果您使用的是 Oracle 或 OpenJDK,则 integer 的hashCode()可能会返回 int 本身(因为 hash 的值也只是一个int值):

/**
 * Returns a hash code for a {@code int} value; compatible with
 * {@code Integer.hashCode()}.
 *
 * @param value the value to hash
 * @since 1.8
 *
 * @return a hash code value for a {@code int} value.
 */
public static int hashCode(int value) {
    return value;
}

The default implementation of HashMap seems heavily java-version dependent. HashMap 的默认实现似乎严重依赖于 java 版本。 The principle (the naïve implementation) is to take the modulus of the hash value and the table length to get the index:原理(naïve 实现)是取 hash 值和表长度的模来获取索引:

index = hash % table.length; // Don't try this, it breaks for negative hash values.

Java 11's implementation seems to do some array-of-trees trickery where it walks the table to find the hash. Java 11 的实现似乎做了一些树数组的诡计,它遍历表以找到 hash。


At the very least, I could reproduce your example with Java 11, and I could break your example by changing this line:至少,我可以使用 Java 11 重现您的示例,并且可以通过更改此行来破坏您的示例:

    Map<Integer, List<String>> lengthToWordsMap = new HashMap<>(4);

Note how even the Integer.hashCode() method doesn't specify how it calculates the hash value, so the fact that it happens to calculate it with the identity function is undocumented and as such should never be relied on.请注意,即使是Integer.hashCode()方法也没有指定它如何计算 hash 值,因此它碰巧使用身份ZC1C425268E68385D1AB5074C17A94F计算它的事实,而且这种情况应该没有记录。

The answer to your question is, it happens because favorable conditions conspire (and specific implementation details), and not because of defined logic.你的问题的答案是,它的发生是因为有利的条件(以及具体的实施细节),而不是因为定义的逻辑。

This is just another approach to solve the problem, with O(N Log N) time complexity and O(N) space.这只是解决问题的另一种方法,具有O(N Log N)时间复杂度和O(N)空间。

public class Solution {
    public static final String arrangeWords(String text) {
        String[] s = text.toLowerCase().split(" ");
        Arrays.sort(s, (a, b) -> a.length() - b.length());
        String rearranged = String.join(" ", s);
        return Character.toUpperCase(rearranged.charAt(0)) + rearranged.substring(1);
    }
}

You question set aside, I guess your method might be O(N ^ 2) time and O(N) space, but I might be totally wrong though.抛开你的问题,我猜你的方法可能是O(N ^ 2)时间和O(N)空间,但我可能完全错了。


References参考

  • For additional details, you can see the Discussion Board .有关其他详细信息,您可以查看讨论板 There are plenty of accepted solutions with a variety of languages and explanations, efficient algorithms, as well as asymptotic time / space complexity analysis 1 , 2 in there.有许多公认的解决方案,其中包含各种语言和解释、高效算法以及渐近时间/空间复杂度分析12

If you are preparing for interviews :如果你正在准备面试

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM