这年头,前端对逻辑能力的要求也是越来越高啊~
以下代码都是我自己独立写的,能力有限,不保证正确。还请大佬们多多指点。
第一题:
请完成函数:
输入参数为两个字符串 s 和 t ,判断 t 是否可以通过删除若干字符得到 s 。
例如: “abcsfs” 可以删除部分字符得到 “bcss” 。
function isInsideString(s, t) {
return false;
}
我的写法:
/*
输入两个字符串 s 和 t ,判断 t 是否能通过删除若干字符得到 s
*/
function isInsideString(s, t) {
// 我的思路:利用 indexOf 方法的第二个参数,一直向后查找。
if (t.length < s.length || !s || !t) return false;
if (t.length === s.length) return s === t;
let index = 0;
for (let i = 0; i < s.length; i++) {
index = t.indexOf(s.charAt(i), index);
console.log(index);
if (index < 0) return false;
index++;
}
return true;
}
第二题:
请完成函数:
两个长度为 n 的字符串的距离定义为这两个字符串对应位置上不同字符的个数。
例如: “babc” 和 “abba” 的距离为3(第0、1、3位置上字符不同)。
输入参数为 m 个长度为 n 的字符串,
生成一个与给定的这 m 个字符串的距离之和最小的长度为 n 的字符串,并输出。
function calcMinDistanceString(strArray) {
return null;
}
我的写法:
/*
两个长度相等都为 n 的字符串的距离,定义为这两字符串对应位置上不同字符的个数。
输入一个字符串数组,里面有 m 个长度相等都为 n 的字符串,
生成一个长度也为 n 的字符串,让它与这 m 个字符串的距离之和最小。
*/
function calcMinDistanceString(strArray) {
// 我的思路:尽量降低每个位置上的字符的差异。
// 找出每个位置上出现次数最多的字符,拼接。
for (let i = 0, m = strArray.length; i < m - 1; i++) {
if (strArray[i].length !== strArray[i + 1].length) return null;
}
let n = strArray[0].length;
let map = Object.create(null);
let res = '';
for (let i = 0; i < n; i++) {
strArray.forEach(str => {
let char = str.charAt(i);
map[char] ? (map[char]++) : (map[char] = 1);
});
let keys = Object.keys(map);
let values = keys.map(key => map[key]); // 保证索引一一对应
let max = Math.max(...values);
let index = values.indexOf(max);
res += keys[index];
map = Object.create(null); // 重置映射关系表
}
return res;
}
第三题:
请完成函数:
已知4种原子的质量,C/H/O/N 分别为 12/1/16/14 ,输入参数为分子式,计算分子量。
例如:“H2O” ,分子量为 1×2+16=18 ,又如 HC11N2 ,分子量为 1×1+12×11+14×2=161
输入异常数据时返回 0
function calcMolecularWeight(str) {
return 0;
}
我的写法:
/*
已知4种原子的质量,C/H/O/N 分别为 12/1/16/14 ,输入分子式,计算分子量,
例如 “H2” 为1×2=2 ,“H2O” 为1×2+16=18 ,输入异常时返回0
*/
function calcMolecularWeight(str) {
let arr = /^([CHON]\d*)+$/.exec(str); // 先测试一下输入的数据格式
if (arr === null) return 0; // 输入格式不对返回 0
arr = str.match(/([CHON]\d*)/g); // match方法全局模式,能直接提取所有匹配
console.log(arr);
let map = {
'C': 12,
'H': 1,
'O': 16,
'N': 14
};
return arr.reduce((res, mol) => {
let atom = mol.charAt(0);
let num = 1;
if (mol.length > 1) num = parseInt(mol.slice(1));
return res + map[atom] * num;
}, 0);
}
第四题:
请完成函数:
输入参数的二维数组表示6个矩形的边长,判断这6个矩形能否组成一个长方体。
二维数组的第一维长度为6,表示6个矩形,第二维长度为2,表示矩形的边长。
输入异常数据时返回 false
function isCuboid(rectangles) {
return false;
}
我的写法:
/*
输入二维数组,含6个子数组,表示6个矩形,每个子数组含2个元素,表示矩形的长和宽。
判断这6个矩形能否拼成正六面体,输入异常数据时返回false
*/
function isCuboid(rectangles) {
// 我的思路:在三维坐标系内,给定任意3个正数,都可以得到正六面体。
// 6个面,最多只能有3种。12个数,最多只能有3种边长。分情况讨论
// 简单拍平,备用
let flat = rectangles.reduce((res, arr) => res.concat(arr), []);
// 检查是否都是正数
let error = flat.every(item => typeof item === 'number' && item > 0);
if (!error) return false; // 输入异常数据返回false
// 统计有几种矩形(面)
let map = Object.create(null);
// 改造成字符串数组,如 ['1,2', '2,3', '3,4', '2,3', ...]
let strArr = rectangles.map(arr => arr.sort((a, b) => a - b).toString());
strArr.forEach(str => {
map[str] ? (map[str]++) : (map[str] = 1);
});
let faces = Object.keys(map); // 每种面
let nums = Object.values(map); // 每种面的重复次数
console.log(map, faces, nums);
// 分情况讨论,
if (faces.length === 1) { // 只有一种面,就必须是正方体
if (nums[0] !== 6) return false;
return new Set(flat).size === 1; // 正方体只能有1种边长
} else if (faces.length === 2) {
if (nums.sort().toString() !== '2,4') return false; // 有两种面
if (new Set(flat).size !== 2) return false; // 只能有2种边长
// 而且重复4次的面必须不是正方形,重复2次的面必须是正方形
let f4 = faces.find(str => map[str] === 4).split(',');
return f4[0] !== f4[1];
// 重复2次的面不需要再判断,因为已受两种面两种边长的限制
} else if (faces.length === 3) {
if (nums.sort().toString() !== '2,2,2') return false; // 有3种面
if (new Set(flat).size !== 3) return false; // 只能有3种边长
// 而且3种面都必须不能是正方形
return faces.every(str => {
let arr = str.split(',');
return arr[0] !== arr[1];
});
}
return false; // 最多只能有3种面
}
就此四题,暂记录于此。