字符串
参考知识点:
# 1. 华为:按字符出现频率降序排列字符串
给定一个字符串,请将字符串里的字符按照出现的频率降序排列。
示例 1:
输入: "book"
输出: "oobk"
解释: 'o'
出现两次,'b'
和 'k'
都只出现一次。
因此 'o'
必须出现在 'b'
和 'k'
之前。此外,"ookb"
也是一个有效的答案。
示例 2:
输入: "cacaca"
输出: "cccaaa"
解释: 'c'
和 'a'
都出现三次。此外,"aaaccc"
也是有效的答案。注意 "cacaca"
是不正确的,因为相同的字母必须放在一起。
思路:
先计数后排序,然后构造新字符串。
function arrangeString(str) {
const cnt = new Array(26).fill(0).map((v, i) => [i, 0]);
for (const ch of str) {
cnt[ch.charCodeAt(0) - 'a'.charCodeAt(0)][1]++;
}
cnt.sort((a, b) => b[1] - a[1]);
const ans = [];
for (const [idx, c] of cnt) {
if (c === 0) {
break;
}
for (let i = 0; i < c; i++) {
ans.push(String.fromCharCode(idx + 'a'.charCodeAt(0)));
}
}
return ans.join("");
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 2. 华为:对比两个缩写字符串复原后一致的字符数
一套针对重复字符串的缩写规则,连续单个字符会被缩写为“重复次数”+“字符”,例如 "AAA"
会被缩写为 "3A"
(单个字符例如 "A"
会被缩写为 "1A"
)。
现给两个缩写后的字符串 recordsA
与 recordsB
,请对比复原后多少一致的字符(即相同的位置的字符是相同的)。
示例1:recordsA="2A2B2A3C"
,recordsB="3C2B2A2D"
输出:2
示例2:recordsA="11A2B3C"
,recordsB="2D5A2B1A3C3B"
输出:6
提示:
0<recordsA.length,recordsB.length<=10000
- 字符中的数字<=
10^6
,需要考虑性能
思路:
对每个缩写字符串,使用两个指针,截取当前缩写的一段字符,同时用两个变量表示当前数字和当前字符。
对于两个缩写字符串的当前数字 nums1
和 nums2
,取得他们的最小值 min
。如果两个字符相同,则将答案加上 min
。然后无论两个字符是否相同,都将 nums1
、nums2
减去 min
,表示已经完成了 min
个字符的判断。
每次判断前,首先判断 nums1
、nums2
的大小关系(因为两者必定是其一为 0 或者均为 0),然后移动双指针取出一段字符。这个过程可以抽象为函数。
注意循环条件,即使指针已经超出字符串长度,但当前数字不为 0,表示当前字符串还未判断完毕。
function consistentChars(recordsA, recordsB) {
const m = recordsA.length, n = recordsB.length;
let ans = 0;
let i1 = 0, j1 = 0, i2 = 0, j2 = 0;
let nums1 = 0, nums2 = 0, ch1 = '', ch2 = '';
while (i1 < m || nums1 > 0 && i2 < n || nums2 > 0) {
if (nums1 < nums2) {
[num1, ch1] = getA();
} else if (nums1 > nums2) {
[num2, ch2] = getB();
} else {
[num1, ch1] = getA();
[num2, ch2] = getB();
}
const min = Math.min(nums1, nums2);
if (ch1 === ch2) {
ans += min;
}
nums1 -= min;
nums2 -= min;
}
return ans;
function getA() {
while (recordsA[j1] >= '0' && recordsA[j1] <= '9') {
j1++;
}
nums1 = Number(recordsA.slice(i1, j1));
ch1 = recordsA[j1++];
i1 = j1;
return [nums1, ch1];
}
function getB() {
while (recordsB[j2] >= '0' && recordsB[j2] <= '9') {
j2++;
}
nums2 = Number(recordsB.slice(i2, j2));
ch2 = recordsB[j2++];
i2 = j2;
return [nums2, ch2];
}
}
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