本篇都是在刷题的时候自己做的部分题解答案记录,非官方题解,如有不足,请见谅😂
下划线转驼峰
描述:要求输入任意层级的一个object对象,对key值进行处理,把下划线分隔的key改为驼峰式的key(doSomething),最后输出这个对象
// 下划线转驼峰
const toCamel = (key) => {
// sddf_ssd
return key.replaceAll(/_+\w/g, (m) => {
return m.replaceAll("_", "").toUpperCase();
});
};
const obj = {
name_lo: "aa",
stamk_god: "333",
probs_dog_good: {
yes_mama: 11,
},
};
const doJson = (obj) => {
for (let key in obj) {
obj[toCamel(key)] = obj[key];
delete obj[key];
if (
Object.prototype.toString.call(obj[toCamel(key)]) ===
Object.prototype.toString()
) {
doJson(obj[toCamel(key)]);
}
}
return obj;
};
console.log(toCamel("name_longly_sex"), doJson(obj));
最长公共子串
描述:查找两个字符串a,b中的最长公共子串。若有多个,输出在较短串中最先出现的那个。
注:子串的定义:将一个字符串删去前缀和后缀(也可以不删)形成的字符串。请和“子序列”的概念分开!
1≤length≤300
输入描述:输入两个字符串
输出描述:返回重复出现的字符
示例1
输入:
abcdefghijklmnop
abcsafjklmnopqrstuvw
输出:
jklmnop
/**
* 查找两个字符串a,b中的最长公共子串
*/
let str1 = "1AB2345CD";
let str2 = "12345EF";
let samestr = "";
const maxlenstr = str1.length > str2.length ? str1 : str2; //较长的字符串
const minstr = str1.length > str2.length ? str2 : str1; //较短
for (let i = 0; i < minstr.length; i++) {
let tempstr = "";
for (let j = i + 1; j <= minstr.length; j++) {
//对每个字符相邻直到末尾的所有子串进行对比
tempstr = minstr.slice(i, j); //剪出相邻的子串
if (tempstr.length < samestr.length) {
//如果子串短于当前存储的最长串则跳过
continue;
}
if (maxlenstr.indexOf(tempstr) > -1 && samestr.length < tempstr.length) {
//与长的字符串匹配,且大于存储的最长串就覆盖
samestr = tempstr;
}
}
}
console.log(samestr);
密码验证合格程序
描述:
密码要求:
1.长度超过8位
2.包括大小写字母.数字.其它符号,以上四种至少三种
3.不能有长度大于2的包含公共元素的子串重复 (注:其他符号不含空格或换行)
1≤n≤100
输入描述:
一组字符串。
输出描述:
如果符合要求输出:OK,否则输出NG
/**
* 密码验证合格程序
*/
const pwd = "123344444";
if (pwd.length <= 8) {
return console.log("NG");
}
let ruleCount = 0;
if (/[a-z]/g.test(pwd)) {
ruleCount++;
}
if (/[A-Z]/g.test(pwd)) {
ruleCount++;
}
if (/\d/g.test(pwd)) {
ruleCount++;
}
if (/\W/g.test(pwd)) {
ruleCount++;
}
if (ruleCount < 3) {
return console.log("NG");
}
for (let i = 0; i < pwd.length; i++) {
for (let j = i + 3; j <= pwd.length; j++) {
const str = pwd.slice(i, j);
if (pwd.lastIndexOf(str) > -1 && pwd.lastIndexOf(str) != i) {
return console.log("NG");
}
}
}
console.log("OK");
VLAN资源池
描述:VLAN是一种对局域网设备进行逻辑划分的技术,为了标识不同的VLAN,引入VLAN ID(1-4094之间的整数)的概念。定义一个VLAN ID的资源池(下称VLAN资源池),资源池中连续的VLAN用开始VLAN-结束VLAN表示,不连续的用单个整数表示,所有的VLAN用英文逗号连接起来。现在有一个VLAN资源池,业务需要从资源池中申请一个VLAN,需要你输出从VLAN资源池中移除申请的VLAN后的资源池。
第一行为字符串格式的VLAN资源池,第二行为业务要申请的VLAN,VLAN的取值范围为[1,4094]之间的整数。
输出描述:从输入VLAN资源池中移除申请的VLAN后字符串格式的VLAN资源池,输出要求满足题目描述中的格式,并且按照VLAN从小到大升序输出。
例子:
1-5
2
输出
1,3-5
/**
* VLAN资源池 -- 遍历数组当含-时获取头尾,且判断如果在区间中就拆分区间 ,n不加入,最后组合到数组中进行删除数值,最后通过-后面的数值排序
*
*/
let arr = ["5", "1-3"];
const n = 10;
const temp = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i].indexOf("-") > -1) {
let start = Number(arr[i].split("-")[0]);
let end = Number(arr[i].split("-")[1]);
if (n <= end && n >= start) {
let str1 = n - start > 1 ? start + "-" + n - 1 : String(start);
let str2 = end - n > 1 ? n + 1 + "-" + end : String(end);
arr.splice(i, 1);
temp.push(str1, str2); //拆分出的区间
}
}
}
arr = arr.concat(temp); //加入拆分的内容
const index = arr.indexOf(String(n));
if (index > -1) {
arr.splice(index, 1); //删除对应数值
}
arr.sort((a, b) => {
const aa = Number(a.split("-")[a.split("-").length - 1]);
const bb = Number(b.split("-")[b.split("-").length - 1]);
return aa - bb;
});
console.log(arr.join());
字符串摘要
给定一个字符串的摘要算法,请输出给定字符串的摘要值。
1、去除字符串中非字母的符号。
2、如果出现连续字符(不区分大小写),则输出:该字符(小写)+ 连续出现的次数。
3、如果是非连续的字符(不区分大小写),则输出:该字符(小写)+ 该字母之后字符串中出现的该字符的次数。
4、对按照以上方式表示后的字符串进行排序:字母和紧随的数字作为一组进行排序,数字大的在前,数字相同的,则按字母进行排序,字母小的在前。
示例:
输入
aabbcc
输出
a2b2c2
/**
* 字符串摘要 -- 滑窗判断重复, 及时对重复的下标i跳加,进行字符串拼接放入数组 最后通过split取出数字排序
*
*/
let n = "bAaCcAcBb".replaceAll(/[^a-zA-z]/g, "").split("");
let arr = [];
for (let i = 0; i < n.length; i++) {
let repeat = 0;
for (let j = i + 1; j < n.length; j++) {
if (n[i].toLowerCase() === n[j].toLowerCase()) { //比对下j个是否和当前i一样的连续字符并累加
repeat++;
} else {
break;
}
}
if (repeat) {
i += repeat;
arr.push(n[i].toLowerCase() + (repeat + 1)); //如有重复推进数组并跳i
} else {
let apear = n
.slice(i + 1)
.filter((item) => item.toLowerCase() === n[i].toLowerCase()).length;
arr.push(n[i] + apear); //否则没有 截断前面的数组并统计字符出现次数
}
}
arr.sort((a, b) => { //排序规则
if (b.split("")[1] === a.split("")[1]){
return a.split("")[0].charCodeAt() - b.split("")[0].charCodeAt();
}
return b.split("")[1] - a.split("")[1];
});
console.log(arr.join(""));
单词接龙
描述:单词接龙的规则是:可用于接龙的单词首字母必须要前一个单词的尾字母相同;当存在多个首字母相同的单词时,取长度最长的单词,如果长度也相等,则取字典序最小的单词;已经参与接龙的单词不能重复使用。
现给定一组全部由小写字母组成单词数组,并指定其中的一个单词作为起始单词,进行单词接龙,请输出最长的单词串,单词串是单词拼接而成,中间没有空格。
输入描述:输入的第一行为一个非负整数,表示起始单词在数组中的索引
输入的第二行为一个非负整数,表示单词的个数N;
接下来的N行,分别表示单词数组中的单词。
输出描述:输出一个字符串,表示最终拼接的单词串。
/**
* 单词接龙 -- while循环不断使用filter头尾相比,多个结果取第一个并排序,没有结果中断循环,每次开始删除上一次生效的word
*
*/
const arr = ["word", "dd", "da", "dc", "dword", "d"];
const start = 4;
let word = arr[start];
const res = [word];
let notfound = false;
while (!notfound) {
arr.splice(arr.indexOf(word), 1); //删除掉上次匹配成功的
let next = arr.filter(
(item) => item.charAt(0) === word.charAt(word.length - 1)
);
if (next.length > 1) {
//多个结果排序后取第一个
let temp = next.sort().sort((A, B) => {
if (B.length !== A.length) {
return B.length - A.length;
}
});
word = temp[0];
res.push(temp[0]);
}
if (next.length === 1) {
res.push(next[0]);
word = next[0];
}
if (next.length === 0) {
notfound = true;
}
}
console.log(res.join(""));
字符串加密
描述:给你一串未加密的字符串str,通过对字符串的每一个字母进行改变来实现加密,加密方式是在每一个字母str[i]偏移特定数组元素a[i]的量,数组a前三位已经赋值:a[0]=1,a[1]=2,a[2]=4。当i>=3时,数组元素a[i]=a[i-1]+a[i-2]+a[i-3],
例如:原文 abcde 加密后 bdgkr,其中偏移量分别是1,2,4,7,13。
/**
* 字符串加密 -- 定义字母表 对原数组遍历加密 当前位置加上偏移算法求余26获取偏移位置拼接
*
*/
let num = "2";
let arr = "abcde";
const zimu = "abcdefghijklmnopqrstuvwxyz";
const list = [];
let sb = "";
for (let j = 0; j < arr.length; j++) {
let pianyi = jiami(j);
let index = (zimu.indexOf(arr.charAt(j)) + pianyi) % 26; //需要取余,防止pianyi值过大
sb += zimu.charAt(index);
}
list.push(sb);
console.log(list[0]);
function jiami(n) {
//根据要求 0=1,1=2,2=4,大于3时 递归入参-1 加 -2 加 -3
if (n == 0) {
return 1;
}
if (n == 1) {
return 2;
}
if (n == 2) {
return 4;
}
return jiami(n - 1) + jiami(n - 2) + jiami(n - 3);
}
字符串重新排序
题目描述:给定一个字符串s,s包含以空格分隔的若干个单词,请对s进行如下处理后输出:
1、单词内部调整:对每个单词字母重新按字典序排序;
2、单词间顺序调整:
1)统计每个单词出现的次数,并按次数降序排列;
2)次数相同时,按单词长度升序排列;
3)次数和单词长度均相同时,按字典序升序排列。
请输出处理后的字符串,每个单词以一个空格分隔。
输入:My sister is in the house not in the yard
输出: in in eht eht My is not adry ehosu eirsst
let word = "My sister is in the house not in the yard".split(" ");
word = word.map((item) => {
return item.split("").sort().join("");
});
let copy = [...word];
const res = word
.sort((a, b) => {
//出现次数
let anums = copy.filter((i) => i === a).length;
let bnums = copy.filter((i) => i === b).length;
if (bnums !== anums) {
//出现次数不等则 次数降序
return bnums - anums;
} else if (b.length !== a.length) {
//出现次数相等且长度不等 长度升序
return a.length - b.length;
} else {
//出现次数相等且长度相等 字典升序
return a.charCodeAt(0) - b.charCodeAt(0);
}
})
.join(" ");
console.log(res)
静态代码扫描服务
题目描述:静态扫描快速快速识别源代码的缺陷,静态扫描的结果以扫描报告作为输出
1、文件扫描的成本和文件大小相关,如果文件大小为N,则扫描成本为N个金币
2、扫描报告的缓存成本和文件大小无关,每缓存一个报告需要M个金币
3、扫描报告缓存后,后继再碰到该文件则不需要扫描成本,直接获取缓存结果
给出源代码文件标识序列和文件大小序列,求解采用合理的缓存策略,最少需要的金币数。
输入:
5
1 2 2 1 2 3 4
1 1 1 1 1 1 1
输出:7
/**
* 静态代码扫描服务
*/
const m = 5;
const ids = [2, 2, 2, 2, 2, 5, 2,2,2];
let idsset = [...new Set(ids)]; //对输入的文件标识去重
const size = [3,3,3,3,3,1,3,3,3];
let sum = 0;
idsset = idsset.forEach(id => {
let idsize = size[ids.indexOf(id)]; //对应的文件大小
//对每个文件进行缓存和不缓存的费用比较,取便宜的费用进行累加
sum += Math.min(
idsize + m, //缓存费用
idsize * ids.filter((item) => item === id).length //不缓存费用
);
});
console.log(sum);
最多提取子串数目
题目描述:给定由[a-z] 26个英文小写字母组成的字符串A和B,其中A中可能存在重复字母,B中不会存在重复字母现从字符串A中按规则挑选一些字母,可以组成字符串B。挑选规则如下:同一个位置的字母只能被挑选一次
被挑选字母的相对先后顺序不能改变求最多可以同时从A中挑选多少组能组成B的字符串
const rl = require("readline").createInterface({ input: process.stdin });
var iter = rl[Symbol.asyncIterator]();
const readline = async () => (await iter.next()).value;
void (async function () {
// Write your code here
let aline = await readline();
let bline = await readline();
let alist = aline.split("");
let blist = bline.split("");
let count = 0;
let n = 1;
while (n) {
let temp = [];
let stack = [...blist]; //栈存储
for (let i = 0; i < alist.length; i++) {
if (stack.length == 0) {
break;
}
if (alist[i] == stack[0]) {
stack.shift(); //出栈
temp.push(i); //存下标
}
}
if (stack.length == 0) { //栈清空表示成功一轮匹配,继续匹配,直到匹配不出来栈无法清空就结束
count++;
while (temp.length > 0) {//删除匹配成功的alist元素
let j = temp.pop();
alist.splice(j, 1);
}
} else {
n = 0;
}
}
console.log(count);
})();
箱子之形摆放
题目描述:有一批箱子(形式为字符串,设为str),要求将这批箱子按从上到下以之形的顺序摆放在宽度为n的空地,请输出箱子的摆放结果。
例如:箱子为ABCDEFG,空地宽度为3,摆放结果如图:
则输出结果为:
AFG
BE
CD
/**
* 箱子之形摆放
*/
let strings = "ABCDEFG 3".split(" ");
let box = strings[0];
let n = Number(strings[1]);
let res = [];
let col = 0;
let w = 0; //宽度
for (let i = 0; i < box.length; i++) {
col = Math.floor(i / n); //当前列数
if (col === 0) {
res[w] = [box[i]];
} else {
res[w].push(box[i]);
}
if (w < n - 1 && col % 2 === 0) {//当小于宽度时且为偶数列宽度递增
w++;
}
if (w > 0 && col % 2 !== 0) {//为奇数列宽度进行递减
w--;
}
}
res.forEach((item) => console.log(item.join("")));
投篮大赛
/**
* 投篮大赛
*/
const arr = ['5', 'D' ,'4', 'C', 'D','9','+' ,'+'];
let res = 0
let i=0;
while (arr[i] !== undefined) {
arr[i] = isNaN(arr[i]) ? arr[i] : Number(arr[i]);
if (arr[i + 1] && arr[i + 1] === "C") { //当下一个为C清除C和当前项
arr.splice(i, 2);
}
if (arr[i] && arr[i] === "D") { //为D 变化为上一个2倍
arr[i] = arr[i - 1] * 2;
}
if (arr[i + 1] && arr[i +1] === "+") { //下一个为+则对当前和上一个相加
arr[i + 1] = arr[i] + Number(arr[i - 1]);
}
res += Number(arr[i]);
i++;
}
console.log(isNaN(res)? -1: res);
寻找链表的中间结点
/**
* 寻找链表的中间结点
*/
const node = ['76892 7 12309','12309 5 -1', '10000 1 76892'];
const head = '10000';
const nodemap = {};
node.forEach(item =>{
const [addr, val, next] = item.split(' ');
nodemap[addr] = { //map地址映射存储所有链表数据
val,
next
}
});
let len = 0;
let currnodeNext = head;
while (currnodeNext !== "-1") { //获取到len的真实链表长度 (链表运动)
currnodeNext = nodemap[currnodeNext].next;
len++;
}
let center = Math.floor(len /2); //中位数
let currt = nodemap[head];
while(center--){ //链表运动到中位数停止 ,从而得到结果
currt = nodemap[currt.next];
}
console.log(currt.val);
获取最大软件版本号
/**
* 获取最大软件版本号
*/
const arr = ["1.05.1", "1.5.01"];
let version1 = arr[0].split("-")[0].replaceAll(".", ""),
version2 = arr[1].split("-")[0].replaceAll(".", "");
if (version1.length > version2.length) {
version2 = version2 + "0".repeat(version1.length - version2.length);
} else {
version1 = version1 + "0".repeat(version2.length - version1.length);
}
if (Number(version1) > Number(version2)) {
return console.log(arr[0]);
}
if (Number(version1) < Number(version2)) {
return console.log(arr[1]);
}
if (
arr[0].split("-")[1].charAt(0).charCodeAt() <
arr[1].split("-")[1].charAt(0).charCodeAt()
) {
console.log(arr[1]);
} else {
console.log(arr[0]);
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。