如何解决CodingBat编码器问题?

问题描述

问题链接https://codingbat.com/prob/p238573

要求: 编写一个函数,用raw中的单词替换code_words中的单词,以使raw中每个单词的第一个出现都被赋予code_words中的第一个未分配的单词。 / p>

encoder([[“ a”],[“ 1”,“ 2”,“ 3”,“ 4”])→[“ 1”]

encoder([[“ a”,“ b”],[“ 1”,“ 2”,“ 3”,“ 4”])→[“” 1,“ 2”]

encoder([[“ a”,“ b”,“ a”],[“ 1”,“ 2”,“ 3”,“ 4”])→[“ 1”,“ 2”,“ 1” ]

我尝试了两种不同的解决方案,但仍然表明我的功能不适用于“其他测试”

第一:

public String[] encoder(String[] raw,String[] code_words) {
          HashMap<String,String> hm = new HashMap<String,String>();
          for (int i=raw.length - 1; i >= 0; i--) {
              hm.put(raw[i],code_words[i]);
          }
            
          
          String [] finalarray = new String[raw.length];
          for (int i=0; i < raw.length; i++) {
            String x = hm.get(raw[i]);
            finalarray[i] = x;
          }
          return finalarray;
        }

所有测试都很好,但是“其他测试”失败了

所以我认为是因为需求中的这一行 raw中每个单词的第一次出现会被分配code_words

中的第一个 未分配 单词

所以我将代码更新为:

public String[] encoder(String[] raw,String>();
          for (int i=0; i < raw.length; i++) {
            String word = raw[i];
            String value = code_words[i];
            if (!hm.containsKey(word)) {
                if (hm.containsValue(value)) {
                    for (int i1=0; i1 < code_words.length; i1++) {
                        value = code_words[i1];
                        if (!hm.containsValue(value)) {
                            hm.put(word,value);
                            break;
                        }
                    }
                
                }
                else {
                    hm.put(word,value);
                }
                
                }   
            }
          String[] finalarray = new String[raw.length];
          for (int i=0; i < raw.length; i++) {
              String x = hm.get(raw[i]);
              finalarray[i] = x;
          }
        return finalarray;
    }

但是它失败了,我不知道为什么。

编辑: 我的(第二个)代码的问题是: 如果我们假设raw = {“ a”,“ a”,“ b”,“ d”} 和代码字= {“ 1”,“ 2”,“ 3”,“ 4”}

我的代码会将字母“ a”分配给“ 1”,将“ b”分配给“ 3”,将d分配给“ 4” 即使它是第一个未分配的字母,也会留下“ 2”个未分配的字母

我提供的代码经过少量调整

public String[] encoder(String[] raw,String>();
          for (int i=0; i < raw.length; i++) {
            String word = raw[i];
            int assigned = 0;
            String value = code_words[assigned];
            if (!hm.containsKey(word)) {
                if (hm.containsValue(value)) {
                    for (int i1=0; i1 < code_words.length; i1++) {
                        value = code_words[i1];
                        if (!hm.containsValue(value)) {
                            hm.put(word,value);
                            assigned++;
                            break;
                        }
                    }
                
                }
                else {
                    hm.put(word,value);
                    assigned++;
                }
                
                }   
            }
          String[] finalarray = new String[raw.length];
          for (int i=0; i < raw.length; i++) {
              String x = hm.get(raw[i]);
              finalarray[i] = x;
          }
        return finalarray;
    }

,但是使用下面提供的代码绝对有效。感谢贡献者!

解决方法

您正在使它变得更加复杂。

是的,您需要hm地图,是的,仅当raw单词在地图中尚未成为键时,才添加它。

但是要跟踪下一个未分配的code_word,您需要的是在code_words数组中的 index

Map<String,String> hm = new HashMap<>();
int unassigned = 0;
for (String word : raw) {
    if (! hm.containsKey(word)) {
        hm.put(word,code_words[unassigned]);
        unassigned++;
    }
}

整个方法的代码可以压缩为:

public String[] encoder(String[] raw,String[] code_words) {
    String[] encoded = new String[raw.length];
    Map<String,String> hm = new HashMap<>();
    for (int i = 0,unassigned = 0; i < raw.length; i++)
        if ((encoded[i] = hm.get(raw[i])) == null)
            hm.put(raw[i],encoded[i] = code_words[unassigned++]);
    return encoded;
}
,

问题

您的第一个想法并不是很糟糕。问题是,您应该将raw中出现的单词的所有所有替换为code_words中第一个未分配的单词。

如何修复

首先让我们分析一下如何解决您的第一个代码。您使用HashMap的想法非常好。显然,如果HashMap中已经存在raw一词,则您不想再次添加它,因此只需在第一次迭代中将其跳过即可。
现在,如果raw中的第 i 个单词在HashMap中没有分配的值,则应将其添加到code_words的第一个未分配的单词中,该单词的索引可能不同于i,因此我们为其分配了另一个索引,比方说j。之后,已经分配了第 j 个单词,而第一个未分配的单词的索引为j + 1。
像这样raw进行一次迭代之后,每个单词在HashMap中都有一个已分配的代码,您可以再对其进行一次迭代并分配值。

代码

您的最终代码将如下所示:

public String[] encoder(String[] raw,String[] code_words) {
    HashMap<String,String> dictionary = new HashMap<>();
    String[] coded = new String[raw.length];
    int j = 0;
    for(int i = 0; i < raw.length; i++) {
        if(!dictionary.containsKey(raw[i])) { //if it has no assigned value
            dictionary.put(raw[i],code_words[j]); //add to hashmap
            j++; //set index to next unassigned
        }
        //do nothing if already found before
    }
    for(int i = 0; i < raw.length; i++) {
        coded[i] = dictionary.get(raw[i]); //get coded word and set in final array
    }
    return coded;
}

我们可以编写出更加紧凑的代码,有些人可能会更喜欢,而另一些人可能会感到更困惑,所以这取决于您。

public String[] encoder(String[] raw,code_words[j++]); //add to hashmap and also increment index of code_words
        }
        coded[i] = dictionary.get(raw[i]);
    }
    return coded;
}

最后一个代码通过了所有测试。

,

只需更新一行

hm.put(raw[i],code_words[raw[i].charAt(0)-'a']);