JavaScript 对象、字符串的统计和排序高频面试题
以下是针对 JavaScript 对象、字符串的统计和排序高频面试题的分类解析,涵盖核心实现思路、代码示例及性能优化要点,结合真题场景整理:
📊 一、字符串统计类题目
1. 统计字符出现频率
题目:统计字符串中每个字符的出现次数,返回 { 字符: 次数 }
对象,忽略大小写和空格。
function countChars(str) {const map = {};for (const char of str.toLowerCase().replace(/\s/g, '')) {map[char] = (map[char] || 0) + 1;}return map;
}
// 示例:countChars("Hello") → { h:1, e:1, l:2, o:1 }
关键点:
- 预处理:转小写
.toLowerCase()
+ 移除空格replace(/\s/g, '')
- 哈希表存储:
map[char] = (map[char] || 0) + 1
实现计数
2. 查找最高频字符 (⭐⭐⭐:挂了美团实习和滴滴提前批)
题目:找出字符串中出现次数最多的字符及次数(多众数时返回全部)。 一个循环,统计时也判断是不是最大,我那天记得但无语住了
,why
function findMaxChar(str) {const map = {};let maxCount = 0, result = [];for (const char of str) {map[char] = (map[char] || 0) + 1;if (map[char] > maxCount) {maxCount = map[char];result = [char];} else if (map[char] === maxCount) {result.push(char);}}return { chars: result, count: maxCount };
}
// 示例:findMaxChar("aabbc") → { chars: ['a','b'], count: 2 }
关键点:
- 动态更新最大值:遍历时同步更新
maxCount
和结果数组 - 多众数处理:
map[char] === maxCount
时追加字符
3. 计算字符串字节长度
题目:一个英文字符占 1 字节,一个中文字符占 2 字节,实现字节统计函数。
function getByteLength(str) {let bytes = 0;for (let i = 0; i < str.length; i++) {bytes += str.charCodeAt(i) > 255 ? 2 : 1;}return bytes;
}
// 示例:getByteLength("你好a") → 5 (2*2 + 1)
关键点:
charCodeAt(i) > 255
判断中文字符
🔄 二、排序类题目
1. 基础排序:数字/字符串数组
题目:对数字数组升序排序,或对字符串按字母顺序/长度排序。
// 数字升序
[3, 1, 4].sort((a, b) => a - b); // [1, 3, 4]
// 字符串按长度排序
['apple', 'kiwi'].sort((a, b) => a.length - b.length); // ['kiwi', 'apple']
// 字符串按字母逆序
'javascript'.split('').sort((a, b) => b.localeCompare(a)).join(''); // 'vtsrponmca'
关键点:
- 数字排序需自定义比较函数避免字典序问题
- 字符串逆序:
localeCompare()
反向比较
2. 对象数组按属性排序
题目:按对象属性(如 age
)排序,相同属性时按第二属性(如 name
)排序。
users.sort((a, b) => {if (a.age !== b.age) return a.age - b.age;return a.name.localeCompare(b.name); // 年龄相同时按名字排序
});
关键点:
- 多级排序:优先比较主属性,次属性作为 fallback
3. 自定义规则排序
题目:按特定规则排序(如先排含 -
的字符串,再按首字母数字排序)。
function customSort(arr) {return arr.sort((a, b) => {if (a.includes('-') !== b.includes('-')) {return a.includes('-') ? -1 : 1; // 含 '-' 的排最前}const numA = parseInt(a.match(/\d+/)?.[0] || Infinity);const numB = parseInt(b.match(/\d+/)?.[0] || Infinity);return numA - numB; // 按首字母数字升序});
}
// 示例:customSort(['A2', 'B1', '-C3']) → ['-C3', 'B1', 'A2']
关键点:
- 规则优先级:通过条件分支实现多级规则
- 数字提取:
parseInt(a.match(/\d+/)[0])
获取首数字
⚙️ 三、复杂场景综合应用
1. 统计后按频次排序
题目:统计字符频率后按频次降序输出字符数组。
function sortByFrequency(str) {const map = {};for (const char of str) map[char] = (map[char] || 0) + 1;return Object.entries(map).sort((a, b) => b[1] - a[1]).map(item => item[0]);
}
// 示例:sortByFrequency("tree") → ['e', 't', 'r'](e 出现2次)
2. 多条件混合排序
题目:对含区域信息的数组如 ['A华东', 'B华南']
,先按首字母排序,再按“东>南>西>北”排序汉字。
function sortArea(areas) {const order = { '东':0, '南':1, '西':2, '北':3 };return areas.sort((a, b) => {if (a[0] !== b[0]) return a[0].localeCompare(b[0]); // 首字母排序const dirA = a.match(/[东南西北]/)?.[0] || '';const dirB = b.match(/[东南西北]/)?.[0] || '';return order[dirA] - order[dirB]; // 按方向优先级排序});
}
// 示例:sortArea(['A华北','A华东']) → ['A华东','A华北']
⚡ 四、性能优化与边界处理
场景 | 优化策略 | 示例 |
---|---|---|
大数据量统计 | 用 Map 替代 Object (避免原型链污染) | const map = new Map(); map.set(char, count) |
频繁字符串操作 | 减少 split /join 调用,改用数组操作 | 直接用 Array.from(str) 替代 str.split('') |
空值/异常处理 | 校验输入类型和空值 | if (typeof str !== 'string') throw Error() |
特殊字符处理 | 用正则过滤非目标字符(如 str.replace(/[^\w]/g, '') ) | 避免统计符号或空格干扰 |
💎 高频考点总结
类别 | 核心题目 | 考察重点 |
---|---|---|
字符串统计 | 字符频率统计、最高频字符、字节长度计算 | 哈希表应用、边界处理 |
基础排序 | 数字/字符串排序、对象属性排序 | sort 方法、比较函数设计 |
自定义规则排序 | 多级排序(字母+汉字)、特殊符号优先级 | 规则抽象能力、正则提取关键信息 |
综合应用 | 统计后排序、混合数据结构处理 | 数据转换链、算法复杂度优化 |
建议练习方向:
- 手写统计函数:重点处理大小写、空格、多字节字符等边界场景;
- 复杂排序:尝试对
[{name: 'Alice', age: 20}, ...]
先按age
降序,age
相同时按name
升序; - 综合题:给定字符串,返回按字符频次降序排列的新字符串(如
"tree"
→"eetr"
)。
以下是一些在 JavaScript 面试中常见的对象和字符串统计与排序相关的高频题目,涵盖了基础知识和进阶技巧,适合用于笔试和手写代码环节:
1. 统计字符串中出现频率最高的字符
题目描述:
给定一个字符串,统计其中出现次数最多的字符及其出现次数。(博客园)
解题思路:
- 使用对象或 Map 来记录每个字符的出现次数。
- 遍历字符串,更新对应字符的计数。
- 遍历计数对象,找出出现次数最多的字符。(掘金)
示例代码:
function findMostFrequentChar(str) {const map = new Map();for (const char of str) {map.set(char, (map.get(char) || 0) + 1);}let maxChar = '', maxCount = 0;for (const [char, count] of map.entries()) {if (count > maxCount) {maxChar = char;maxCount = count;}}return { char: maxChar, count: maxCount };
}
该方法利用 Map 的特性,简洁高效地完成了字符频率统计。(CSDN)
2. 统计子字符串在字符串中出现的次数
题目描述:
实现一个函数,接受两个参数:主字符串和子字符串,返回子字符串在主字符串中出现的次数。(CSDN)
解题思路:
- 使用
indexOf
方法查找子字符串的位置。 - 每次找到后,从下一个位置继续查找,直到找不到为止。
示例代码:
function countSubstr(str, target) {let count = 0;let index = str.indexOf(target);while (index !== -1) {count++;index = str.indexOf(target, index + target.length);}return count;
}
该方法适用于查找非重叠的子字符串出现次数。(博客园)
3. 根据字符出现次数对字符串进行排序
题目描述:
对字符串中的字符按照出现次数从高到低排序;如果出现次数相同,则按照 ASCII 码从小到大排序。(博客园)
解题思路:
- 使用对象或 Map 统计每个字符的出现次数。
- 将统计结果转换为数组,使用自定义的排序函数进行排序。
- 根据排序结果构建新的字符串。(CSDN, 博客园)
示例代码:
function sortByFrequency(str) {const freqMap = {};for (const char of str) {freqMap[char] = (freqMap[char] || 0) + 1;}return Object.entries(freqMap).sort((a, b) => {if (b[1] !== a[1]) return b[1] - a[1];return a[0].charCodeAt() - b[0].charCodeAt();}).map(([char]) => char.repeat(freqMap[char])).join('');
}
该方法结合了频率统计和排序,能够满足复杂的排序需求。
4. 对对象数组按照某个属性进行排序
题目描述:
给定一个学生成绩数组,每个元素包含 chinese
、math
、english
三个属性,要求按照总成绩从高到低排序。(CSDN)
解题思路:
- 使用
Array.prototype.sort
方法,比较函数中计算每个学生的总成绩并进行比较。
示例代码:
function sortByTotalScore(students) {return students.sort((a, b) => {const totalA = a.chinese + a.math + a.english;const totalB = b.chinese + b.math + b.english;return totalB - totalA;});
}
该方法适用于对对象数组进行多属性计算后的排序。(博客园)
5. 找出字符串中第一个不重复的字符
题目描述:
给定一个字符串,找出其中第一个只出现一次的字符。(CSDN)
解题思路:
- 使用对象记录每个字符的出现次数。
- 遍历字符串,找到第一个出现次数为 1 的字符。(牛客网)
示例代码:
function firstUniqueChar(str) {const count = {};for (const char of str) {count[char] = (count[char] || 0) + 1;}for (const char of str) {if (count[char] === 1) return char;}return null;
}
该方法高效地找出了第一个不重复的字符。(liayal.com)
这些题目不仅考察了 JavaScript 的基本语法和数据结构的使用,还涉及了算法思维和代码优化能力。建议在准备面试时,深入理解每道题的解题思路,并尝试手写实现,以提升实战能力。