JS Guide JS Guide
首页
  • JS 部分
  • HTML 部分
  • CSS 部分
  • Vue
  • React & Angular
  • 数据结构、算法、OS
  • 计网、浏览器
  • 杂项
笔试
面试
资源
资讯
  • 关于本站
  • 更新历史
  • 贡献指南
  • 文档规范
  • 常见问题
GitHub (opens new window)
首页
  • JS 部分
  • HTML 部分
  • CSS 部分
  • Vue
  • React & Angular
  • 数据结构、算法、OS
  • 计网、浏览器
  • 杂项
笔试
面试
资源
资讯
  • 关于本站
  • 更新历史
  • 贡献指南
  • 文档规范
  • 常见问题
GitHub (opens new window)
  • 面试相关说明
  • 解释代码题

  • 手撕代码题

    • 数学
    • 字符串
      • 1. 华为:按字符出现频率降序排列字符串
      • 2. 华为:对比两个缩写字符串复原后一致的字符数
    • 数组
    • 手写函数实现
  • 个人相关

  • 面试相关
  • 手撕代码题
卡洛
2022-11-02
目录

字符串

参考知识点:

  • JS 知识点 - 字符串

# 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("");
}
1
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

提示:

  1. 0<recordsA.length,recordsB.length<=10000
  2. 字符中的数字<=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];
  }
}
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
在 GitHub 中编辑此页 (opens new window)
上次更新于: 2022/11/3 23:25:22
数学
数组

← 数学 数组→

Theme by Vdoing | Copyright © 2022-2022 Carlo | Powered by VuePress
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式