0824-山羊拉丁文

Raphael Liu Lv10

给你一个由若干单词组成的句子 sentence ,单词间由空格分隔。每个单词仅由大写和小写英文字母组成。

请你将句子转换为 山羊拉丁文( Goat Latin (一种类似于 猪拉丁文 - Pig Latin
的虚构语言)。山羊拉丁文的规则如下:

  • 如果单词以元音开头('a', 'e', 'i', 'o', 'u'),在单词后添加"ma"
    • 例如,单词 "apple" 变为 "applema"
  • 如果单词以辅音字母开头(即,非元音字母),移除第一个字符并将它放到末尾,之后再添加"ma"
    • 例如,单词 "goat" 变为 "oatgma"
  • 根据单词在句子中的索引,在单词最后添加与索引相同数量的字母'a',索引从 1 开始。
    • 例如,在第一个单词后添加 "a" ,在第二个单词后添加 "aa" ,以此类推。

返回将 sentence 转换为山羊拉丁文后的句子。

示例 1:

**输入:** sentence = "I speak Goat Latin"
**输出:** "Imaa peaksmaaa oatGmaaaa atinLmaaaaa"

示例 2:

**输入:** sentence = "The quick brown fox jumped over the lazy dog"
**输出:** "heTmaa uickqmaaa rownbmaaaa oxfmaaaaa umpedjmaaaaaa overmaaaaaaa hetmaaaaaaaa azylmaaaaaaaaa ogdmaaaaaaaaaa"

提示:

  • 1 <= sentence.length <= 150
  • sentence 由英文字母和空格组成
  • sentence 不含前导或尾随空格
  • sentence 中的所有单词由单个空格分隔

方法一:找到每一个单词 + 模拟

思路与算法

我们可以对给定的字符串 sentence 进行一次遍历,找出其中的每一个单词,并根据题目的要求进行操作。

在寻找单词时,我们可以使用语言自带的 split() 函数,将空格作为分割字符,得到所有的单词。为了节省空间,我们也可以直接进行遍历:每当我们遍历到一个空格或者到达 sentence 的末尾时,我们就找到了一个单词。

当我们得到一个单词 w 后,我们首先需要判断 w 的首字母是否为元音字母。我们可以使用一个哈希集合 vowels 存储所有的元音字母 aeiouAEIOU,这样只需要判断 w 的首字母是否在 vowels 中。如果是元音字母,那么单词本身保持不变;如果是辅音字母,那么需要首字母移到末尾,这里使用语言自带的字符串切片函数即可。在这之后,我们需要在末尾添加 m 以及若干个 a,因此可以使用一个变量 cnt 记录需要添加的 a 的个数,它的初始值为 1,每当我们得到一个单词,就将它的值增加 1。

代码

[sol1-C++]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Solution {
public:
string toGoatLatin(string sentence) {
unordered_set<char> vowels = {'a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U'};

int n = sentence.size();
int i = 0, cnt = 1;
string ans;

while (i < n) {
int j = i;
while (j < n && sentence[j] != ' ') {
++j;
}

++cnt;
if (cnt != 2) {
ans += ' ';
}
if (vowels.count(sentence[i])) {
ans += sentence.substr(i, j - i) + 'm' + string(cnt, 'a');
}
else {
ans += sentence.substr(i + 1, j - i - 1) + sentence[i] + 'm' + string(cnt, 'a');
}

i = j + 1;
}

return ans;
}
};
[sol1-Java]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Solution {
public String toGoatLatin(String sentence) {
Set<Character> vowels = new HashSet<Character>() {{
add('a');
add('e');
add('i');
add('o');
add('u');
add('A');
add('E');
add('I');
add('O');
add('U');
}};

int n = sentence.length();
int i = 0, cnt = 1;
StringBuffer ans = new StringBuffer();

while (i < n) {
int j = i;
while (j < n && sentence.charAt(j) != ' ') {
++j;
}

++cnt;
if (cnt != 2) {
ans.append(' ');
}
if (vowels.contains(sentence.charAt(i))) {
ans.append(sentence.substring(i, j));
} else {
ans.append(sentence.substring(i + 1, j));
ans.append(sentence.charAt(i));
}
ans.append('m');
for (int k = 0; k < cnt; ++k) {
ans.append('a');
}

i = j + 1;
}

return ans.toString();
}
}
[sol1-C#]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class Solution {
public string ToGoatLatin(string sentence) {
ISet<char> vowels = new HashSet<char>();
vowels.Add('a');
vowels.Add('e');
vowels.Add('i');
vowels.Add('o');
vowels.Add('u');
vowels.Add('A');
vowels.Add('E');
vowels.Add('I');
vowels.Add('O');
vowels.Add('U');

int n = sentence.Length;
int i = 0, cnt = 1;
StringBuilder ans = new StringBuilder();

while (i < n) {
int j = i;
while (j < n && sentence[j] != ' ') {
++j;
}

++cnt;
if (cnt != 2) {
ans.Append(' ');
}
if (vowels.Contains(sentence[i])) {
ans.Append(sentence.Substring(i, j - i));
} else {
ans.Append(sentence.Substring(i + 1, j - i - 1));
ans.Append(sentence[i]);
}
ans.Append('m');
for (int k = 0; k < cnt; ++k) {
ans.Append('a');
}

i = j + 1;
}

return ans.ToString();
}
}
[sol1-Python3]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Solution:
def toGoatLatin(self, sentence: str) -> str:
vowels = {"a", "e", "i", "o", "u", "A", "E", "I", "O", "U"}

n = len(sentence)
i, cnt = 0, 1
words = list()

while i < n:
j = i
while j < n and sentence[j] != " ":
j += 1

cnt += 1
if sentence[i] in vowels:
words.append(sentence[i:j] + "m" + "a" * cnt)
else:
words.append(sentence[i+1:j] + sentence[i] + "m" + "a" * cnt)

i = j + 1

return " ".join(words)

[sol1-JavaScript]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
var toGoatLatin = function(sentence) {
const vowels = new Set();
vowels.add('a');
vowels.add('e');
vowels.add('i');
vowels.add('o');
vowels.add('u');
vowels.add('A');
vowels.add('E');
vowels.add('I');
vowels.add('O');
vowels.add('U');

const n = sentence.length;
let i = 0, cnt = 1;
ans = '';

while (i < n) {
let j = i;
while (j < n && sentence[j] !== ' ') {
++j;
}

++cnt;
if (cnt !== 2) {
ans += ' ';
}
if (vowels.has(sentence[i])) {
ans += sentence.substring(i, j);
} else {
ans += sentence.slice(i + 1, j);
ans += sentence[i];
}
ans += 'm';
for (let k = 0; k < cnt; ++k) {
ans += 'a';
}

i = j + 1;
}

return ans;
};
[sol1-C]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#define MAX_LATIN_LEN 2048

char * toGoatLatin(char * sentence){
int vowels[256];
memset(vowels, 0, sizeof(vowels));
vowels['a'] = 1;
vowels['e'] = 1;
vowels['i'] = 1;
vowels['o'] = 1;
vowels['u'] = 1;
vowels['A'] = 1;
vowels['E'] = 1;
vowels['I'] = 1;
vowels['O'] = 1;
vowels['U'] = 1;

int n = strlen(sentence);
int i = 0, cnt = 1;
char * ans = (char *)malloc(sizeof(char) * MAX_LATIN_LEN);
int pos = 0;

while (i < n) {
int j = i;
while (j < n && sentence[j] != ' ') {
++j;
}

++cnt;
if (cnt != 2) {
ans[pos++] = ' ';
}
if (vowels[sentence[i]]) {
memcpy(ans + pos, sentence + i, sizeof(char) * (j - i));
pos += j - i;
ans[pos++] = 'm';
memset(ans + pos, 'a', cnt);
pos += cnt;
} else {
memcpy(ans + pos, sentence + i + 1, sizeof(char) * (j - i - 1));
pos += j - i - 1;
ans[pos++] = sentence[i];
ans[pos++] = 'm';
memset(ans + pos, 'a', cnt);
pos += cnt;
}
i = j + 1;
}
ans[pos] = 0;
return ans;
}
[sol1-Golang]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var vowels = map[byte]struct{}{'a': {}, 'e': {}, 'i': {}, 'o': {}, 'u': {}, 'A': {}, 'E': {}, 'I': {}, 'O': {}, 'U': {}}

func toGoatLatin(sentence string) string {
ans := &strings.Builder{}
for i, cnt, n := 0, 1, len(sentence); i < n; i++ {
if cnt > 1 {
ans.WriteByte(' ')
}
start := i
for i++; i < n && sentence[i] != ' '; i++ {}
cnt++
if _, ok := vowels[sentence[start]]; ok {
ans.WriteString(sentence[start:i])
} else {
ans.WriteString(sentence[start+1 : i])
ans.WriteByte(sentence[start])
}
ans.WriteByte('m')
ans.WriteString(strings.Repeat("a", cnt))
}
return ans.String()
}

复杂度分析

  • 时间复杂度:O(n^2),其中 n 是字符串 sentence 的长度。虽然我们对字符串只进行了常数次遍历,但是返回的字符串长度的数量级是 O(n^2) 的。考虑最坏的情况,字符串 sentence 包含 75 个单词 a,此时返回的字符串的长度为:

    75 + 75 + \sum_{i=2}^{76} i + 74

    这四部分分别为:单词 a 的长度,添加的 m 的长度,添加的 a 的长度,空格的长度。

  • 空间复杂度:O(n^2) 或 O(n),取决于使用的语言的字符串是否可修改。如果可以修改,我们只需要 O(n) 的空间临时存储字符串切片;如果不可以修改,我们需要 O(n^2) 的空间临时存储所有单词修改后的结果。注意这里不计入返回字符串使用的空间。

 Comments
On this page
0824-山羊拉丁文