ARTS是
由左耳朵耗子--陈皓
发起的一个活动: 每周至少做一个leetcode的算法题、阅读并点评至少一篇英文技术文章、学习至少一个技术技巧、分享一篇有观点和思考的文章。(也就是Algorithm、Review、Tip、Share简称ARTS),至少坚持一年。
ARTS 019
这是第19篇
Algorihm 算法题
804. Unique Morse Code Words
Difficulty Easy
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.
Solution
Language: C
方法1:就是最容易想到的方法, 直接把单词转换为摩尔玛,然后进行比较,去重
int uniqueMorseRepresentations(char** words, int wordsSize) {
char *morse[26] = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
//convert words to morse
char **chatToMorse = (char **)malloc(sizeof(char*) * wordsSize);
int index = 0;
while (index < wordsSize) {
char *word = words[index];
char *charMorse = NULL;
for (int j = 0; j < strlen(word); j++) {
char charter = word[j];
char *newmorse = morse[charter - 'a'];
if (charMorse == NULL) {
char *result = malloc(strlen(newmorse)+1);
memset(result, '\0', strlen(newmorse)+1);
strcpy(result, newmorse);
charMorse = result;
}
else{
char *result = malloc(strlen(charMorse)+strlen(newmorse)+1);//+1 for the zero-terminator
memset(result, '\0', strlen(charMorse)+strlen(newmorse)+1);
strcpy(result, charMorse);
strcat(result, newmorse);
free(charMorse);
charMorse = result;
}
}
chatToMorse[index] = charMorse;
++index;
}
int falg = 0;
for (int m =0; m < wordsSize; m++) {
char * ms = chatToMorse[m];
if(ms == NULL){
continue;
}
for(int n = m+1; n <wordsSize;n++ ){
char * ns = chatToMorse[n];
if (ns != NULL) {
int res = strcmp(ms,ns);
if (res ==0) {
chatToMorse[n] = NULL;
falg++;
}
}
}
}
return wordsSize -falg;
}
方法2:这个方法的思路和我的是一样的但是比我的快,应该是因为他没有动态分配内存。还有一个就是在最后做去重计算的时候和我的不一样。但是这个代码比我的好,因为他对代码中不同的功能进行了方法封装,有面向对象的思想。
char *transMorse(const char alphabet){
char *morseCode[] = { ".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.." };
return morseCode[alphabet-'a'];
}
void transMorseString(char *word, char *morseString){
char *morseTempt;
while(*word){
morseTempt = transMorse(*word);
word++;
while(*morseTempt){
*morseString = *morseTempt;
morseString++;
morseTempt++;
}
}
return;
}
int uniqueMorseRepresentations(char** words, int wordsSize) {
char morseString[100][50] = {""};
for(int i = 0 ; i<wordsSize ; ++i){
transMorseString(words[i], morseString[i]);
}
//上面的方法h都好理解,就是把字符串转为Morse码
//下面的这个去重计算 感觉不好理解
for(int i = 0 ; i<wordsSize ; ++i){
for(int j = i+1 ; j<wordsSize ; ++j){
while(wordsSize>1 && j<wordsSize && !strcmp(morseString[i], morseString[j])){
strcpy(morseString[j], morseString[wordsSize-1]);
--wordsSize;
}
}
}
return wordsSize;
}
方法3: 这个方法的优点:
- 字符串转摩尔码的时候用了二维方法的时候 比较方便
- 去重的时候用到了集合(set)的概念
特别是第2点,集合的思路,这种情况不就是集合的用武之地吗,自己却没想到。
int addToSet(char** set, int setCount, char* buf);
int uniqueMorseRepresentations(char** words, int wordsSize) {
char* morse[26] = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."};
char* set[100];
int setCount = 0;
//1. 字符串转摩尔码的时候用了二维方法的时候 比较方便
//2. 去重的时候用到了集合(set)的概念
int i = 0;
for(i = 0; i < wordsSize; i++) {
char* buf = malloc(sizeof(char) * 60);
buf[0] = '\0';
int j = 0;
for(j = 0; j < strlen(words[i]); j++) {
char* cat = strcat(buf, morse[words[i][j] - 97]);
printf("add: %c %s, all is: %s", words[i][j], morse[words[i][j] - 97], cat);
}
setCount = addToSet(set, setCount, buf);
printf("\n");
}
for(i = 0; i < setCount; i++) {
free(set[i]);
}
return setCount;
}
int addToSet(char** set, int setCount, char* buf) {
int i = 0;
for(i = 0; i < setCount; i++) {
printf("compare: %s %s", set[i], buf);
if(strcmp(set[i], buf) == 0) {
return setCount;
}
}
set[i] = buf;
return ++i;
}
方法4: 这个方法的思路也很好,把摩尔玛看做是二进制的0和1,.代表0,1代表- 。具体看代码注释
typedef struct {
char len;
char val;
} morseCode;
morseCode codeTable[] = {
{2, 2}, /* a .- 10*/
{4, 7}, /* b -... 0111*/
{4, 5}, /* c -.-. 0101 */
{3, 3},
{1, 1},
{4,13},
{3, 1},
{4,15},
{2, 3},
{4, 8},
{3, 2},
{4,11},
{2, 0},
{2, 1},
{3, 0},
{4, 9},
{4, 2},
{3, 5},
{3, 7},
{1, 0},
{3, 6},
{4,14},
{3, 4},
{4, 6},
{4, 4},
{4, 3}
};
typedef struct{
int len;
int val;
}morseString;
morseString getmorseString(char* s) {
morseString str;
str.len = 0;
str.val = 0;
char *p = s;
while(*p != '\0')
{
char c = *p;
if (c < 'a' || c > 'z'){
printf("Invalid input *p = %c\n", c);
p++;
continue;
}
morseCode code = codeTable[c - 'a'];
str.len += code.len;//记录单词转为摩尔码,也就是二进制之后的位数,当数据很长时有用,如果数据较短,比如没有超过64位或32位。但是超过之后这个就有用了
str.val = (str.val << (code.len)) + code.val;//把str.val看成二进制数据 就容易理解了
p++;
}
return str;
}
int uniqueMorseRepresentations(char** words, int wordsSize) {
int result = -1;
morseString stack[100];
for(int i = 0; i < wordsSize; i++)
{
morseString str = getmorseString(words[i]);
bool foundone = false;
for (int j = 0; j <= result; j++)
{
// check one by one if str in stack
// zstack[j].len == str.len 这个判断当摩尔码的二进制长度超过机器的最大字长时才有用。
// 如果没有超过最大字长,二进制表示相等(stack[j].val == str.val),二进制的长度必然相等
if (stack[j].len == str.len && stack[j].val == str.val) {
foundone = true;
break;
}
}
if (!foundone)
{
stack[++result] = str;
}
}
return result + 1;
}
方法5 : 中规中矩的做法,用到了二维数组,比我的写法简单
int uniqueMorseRepresentations(char** words, int wordsSize) {
char transBuffer[50] = {0};
char transCode[100][50] = {0}; //Store the translation code
char* morseCode[] = {".-","-...","-.-.","-..",".","..-.","--.","....","..",".---","-.-",".-..","--","-.","---",".--.","--.-",".-.","...","-","..-","...-",".--","-..-","-.--","--.."}; // 'a' ~ 'z' Morse Code Table
int j, k;
int existFlag = 0;
int transCodeNum = 0; //Different translation code numbers
for(int i=0; i < wordsSize; i++)
{
j = 0;
k = 0;
existFlag = 0; //Reset the flag
memset(transBuffer, 0, sizeof(transBuffer)); //Reset the buffer
while(words[i][j] != '\0')
{
k = words[i][j] - 'a'; //get the number of letters
strncat(transBuffer, morseCode[k], sizeof(morseCode[k])); //translate the letter by morseCode
j++;
}
for(int z = 0; z < transCodeNum && !existFlag; z++) //Confirm transCode has already store same code
if(strncmp(transCode[z], transBuffer, sizeof(transBuffer)) == 0)
existFlag = 1;
if(!existFlag) //if the code isn't exist, store it
strncpy(transCode[transCodeNum++], transBuffer, sizeof(transBuffer));
}
return transCodeNum;
}
Review
这篇文章讲的是:如何成为一名更好的软件开发人员 讲了除了开发技能之外的东西: 1 了解整个开发流程。建议开发者不仅仅只关注编码,要熟悉整个开发流程,从模糊的想法到精心设计的解决方案的转换过程,以及软件开发完成之后,进行的测试、部署、监视、分析和改进。这样可以让大家互相理解,减少由于互相不了解其他人的工作而导致的沟通障碍 2 了解客户的需求,要和客户交流,做到互相信任,及时的像客户反馈进度和结果 3 对于不同的工作选择不同的方案或工具,不能把已有的技能和经验用到所有的事情上。 4 站在巨人的肩膀上,要善于利用第三方工具,而不是每次都自己重头开发, 5 学习知识的基本原理,不能盲目追求新知识,要搞清知识背后的原理。
翻译参见: https://dandan2009.github.io/2018/12/18/how-to-become-a-better-software-developer/ 原文参见:https://medium.com/devtrailsio/how-to-become-a-better-software-developer-dd16072c974e
Tips
之前用Instruments来测试APP启动时间是,只能记录某一个方法的执行事件,现在可以使用Signposts 来打点记录APP每行代码的运行时间: 参见WWDC2018 Measuring Performance Using Logging: https://developer.apple.com/videos/play/wwdc2018/405/
这有一个译文你可以看下: https://blog.csdn.net/tugele/article/details/81252603
上面给出的例子是基于swift的,在Objective-C中可以使用C语言版本:
os_log_t log = os_log_create("com.example.your-app", "RefreshOperations");
os_signpost_id_t log_t = os_signpost_id_generate(log);
os_signpost_interval_begin(log, log_t, "Fetch Asset");
你的代码
os_signpost_interval_end(log, log_t, "Fetch Asset");
os_signpost_interval_begin(log, log_t, "Fetch Asset1");
你的代码
os_signpost_interval_end(log, log_t, "Fetch Asset1");
Share
招聘行情:https://readhub.cn/jobs
谷歌学术、维基百科、谷歌翻译、Gmail网页版、Google 照片、Google 文档、Google Keep、Google 地球、Google 图书、Chrome同步、Pixiv、Steam社区、GitHub Releases、Pinterest、Vimeo、Yandex、Tumbl YouTube、Twitter、Facebook、Google+、Google Play、Google Drive、Blogger、部分新闻网站、Instagram
英文学习:https://learnamericanenglishonline.com/Red%20Level/R1%20Do.html
解密 Runloop: http://mrpeak.cn/blog/ios-runloop/
mac 开源播放器:1.5 万star, IINA is the modern video player for macOS. https://github.com/lhc70000/iina
通过开发的小程序赚钱的例子:https://www.v2ex.com/t/515777
可以访问Google:https://sss.cnsdhh.com/
搜索颜色的网站:https://picular.co/,搜索出来的颜色是一个色系的,不是单一的一种颜色