关注 每天一道编程题 专栏,一起学习进步。

题目

International Morse Code defines a standard encoding where each letter is mapped to a series of dots and dashes, as follows: “a” maps to “.-”, “b” maps to “-…”, “c” maps to “-.-.”, and so on.

For convenience, the full table for the 26 letters of the English alphabet is given below:

[".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."]

Now, given a list of words, each word can be written as a concatenation of the Morse code of each letter. For example, “cba” can be written as “-.-…–…”, (which is the concatenation “-.-.” + “-…” + “.-”). We’ll call such a concatenation, the transformation of a word.

Return the number of different transformations among all words we have.

Example:
Input: words = [“gin”, “zen”, “gig”, “msg”]
Output: 2
Explanation:
The transformation of each word is:
“gin” -> “–…-.”
“zen” -> “–…-.”
“gig” -> “–…--.”
“msg” -> “–…--.”

There are 2 different transformations, “–…-.” and “–…--.”.

Note:

The length of words will be at most 100.
Each words[i] will have length in range [1, 12].
words[i] will only consist of lowercase letters.

分析

题意:给定一个字符串数组,将其转换成摩斯密码,然后返回这些摩斯密码的组数(相同的摩斯密码为一组)

思路:
首先肯定是将每个字符串转换成摩斯密码,只需要遍历每个字符串,按转换规则转换即可;
然后计算不同摩斯密码的组数:
有两种方法:

  1. 初始化一个计数器,遍历所有摩斯密码对比即可,不同时将计数器+1。
  2. 将所有摩斯密码进行去重,然后计算去重后的个数(set有自动去重功能)

解答

下面答案摘自评论区大神解答,非常的巧妙。解释在注释中

class Solution {
    public int uniqueMorseRepresentations(String[] words) {
        String[] d = {".-", "-...", "-.-.", "-..", ".", "..-.", "--.", "....", "..", ".---", "-.-", ".-..", "--", "-.", "---", ".--.", "--.-", ".-.", "...", "-", "..-", "...-", ".--", "-..-", "-.--", "--.."};
        //创建一个Set,用于存放最终结果,实现自动去重
        Set<String> s = new HashSet<>();
        //遍历每个字符串,假设现在是words={"gin","zen"}
        for (String w : words) {
        	//此时w="gin"
        	//创建一个临时的字符串,用于存放转码后的摩斯密码,用StringBuilder是因为它有append函数
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < w.length(); ++i)
            	//i=0, w.charAt(i)='g'
            	/*
            	这就是最巧妙的地方
				摩斯密码转换表对应的是26个大小写字母,char底层实现是int,
				利用w.charAt(i)='g'-'a',能够得到'g'在摩斯密码数组中的下标,
				通过d[w.charAt(i) - 'a'],就能拿到'g'对应的摩斯码
				*/
				//将摩斯码加入到临时字符串中
                sb.append(d[w.charAt(i) - 'a']);
            //将临时字符串加入到set集合
            s.add(sb.toString());
        }
        //最终返回集合的长度即可,重复的摩斯码已经被忽略了。
        return s.size();
    }
}

上述算法的亮点就在于,通过d[w.charAt(i) - ‘a’],实现了字母到摩斯码的映射。