算法

262 阅读5分钟

字符串统计(全量字符集与已占用字符集)

var str = "a:3,b:5,c:2@a:1,b:2"
function getAlreadyUsed (str) {
	var firstStr = str.slice(0, str.indexOf('@'));
	var firstArr = firstStr.split(',')
 
	var lastStr = str.slice(str.indexOf('@')+1);
	var lastArr = lastStr.split(',');
 
	// 存储全量
	var map1 = new Map()
	// 存储已占用
	var map2 = new Map()
	for(let key of firstArr) {
		map1.set(key[0], key[2])
	}
	for(let key of lastArr) {
		map2.set(key[0], key[2])
	}
 
	for(let key of map2.keys()) {
		if(map1.has(key)) {
			var tmpVal = (+map1.get(key)) - (+map2.get(key))
			if(tmpVal) {
				map1.set(key, tmpVal)
			} else {
				map1.delete(key)
			}
		}
	}
 
	var newStr = ""
	for(let [key, value] of map1) {
		newStr+= `${key}:${value},`
	}
	console.log(newStr.substring(0, newStr.length-1))
}
getAlreadyUsed(str)
 

寻找身高相近的小朋友

function compareHigh(arr,len,tall) {
    let map = new Map()
    for(let i = 0 ; i < len ; i++){
        const frequent = Math.abs(tall - arr[i])
        map.set(arr[i],frequent)
    }
    const list = [...map.keys()]
    list.sort(function(a,b) {
        if(map.get(a) == map.get(b)) {
            return a-b 
        } 
        else {
            return map.get(a) - map.get(b)
        }
    })
 
    return list
}
 
console.log(compareHigh([95,96,97,102,101,99,98,103,104,105],10,100))
 
//打印结果为:[
//   99, 101, 98, 102,
//   97, 103, 96, 104,
//   95, 105
// ]

火星文计算


let str = '7#6$5#12'
let test1 = /[0-9]+\$[0-9]+/
let test2 = /[0-9]+#[0-9]+/

while (str.indexOf('$')>-1){
    test('$')
}
while (str.indexOf('#')>-1){
    test('#')
}
console.log(str);

function test(type){
    let test = ''
    if(type==='$'){
        test = test1
    }else if (type==='#'){
        test = test2
    }
    str = str.replace(test,e=>{
        let x= Number(e.split(type)[0])
        let y= Number(e.split(type)[1])
        if(type==='$'){
            return 3*x+y+2
        }else if(type==='#'){
            return 2*x+3*y+4
        }else {
            return e
        }
    })
}

最长的指定瑕疵度的元音子串



const getLongestFlawedVowelSubstrLen = (flaw, input) => {
    input = input.toLowerCase()
    //利用hash算法确定是否为元音
    let au = {
        a: 1,
        e: 1,
        i: 1,
        o: 1,
        u: 1
    }
    let left = 0
    let right = 0
    let arr = []
    let count = 0
    //每次循环右指针向右进一格,直到遍历完数组
    for (right = 0; right < input.length; right++) {
        //利用哈希算法判断右指针是否为元音,即子串结尾要求时元音
        let isRightYuan = au[input[right]] === 1 ? true : false
        if (isRightYuan === false) {
            count++
        }
        //要求足够的瑕疵度
        if (isRightYuan === false || count < flaw) {
            continue
        }
        //足够的瑕疵度,且左边的也是元音,则记录该子串
        if (count === flaw && au[input[left]] === 1) {
            let temp = input.substring(left, right + 1)
            arr.push(temp)
            continue
        }
        //当瑕疵度大于要求的瑕疵度或子串左边非元音时,需要移动左指针
        while (count > flaw || au[input[left]] !== 1) {
            left++
            if (au[input[left - 1]] !== 1) {
                count--
            }
            if (left > right) {
                left = right
                break
            }
        }
        //记录跳出循环时是否符合要求
        if (count == flaw && au[input[left]] === 1) {
            let temp = input.substring(left, right + 1)
            arr.push(temp)
        }
    }
    if (arr.length > 1) {
        //按长度大小给子串排序
        arr.sort((a, b) => b.length - a.length)
        if (arr.length > 0) {
            return arr[0].length
        }
    } else if (arr.length === 1) {
        return arr[0].length
    } else {
        return 0
    }
}
console.log(getLongestFlawedVowelSubstrLen(0, 'asdbuiodevauufgh'))

// 解析
// 注意每次如果先判断左指针则每次都要将右指针从头判断到尾,而先判断右指针,左指针只用在原先的基础上移动到下一个符合条件的位置,这样可以节省很多多余的判断。

// 核心思想
// 先确定右指针是否为元音,否就右移,是就判断瑕疵度是否够且左指针也为元音,都满足才记录,不满足,瑕疵度不够就继续右移右指针,瑕疵度超过就右移左指针,直到瑕疵度小于或等于指定瑕疵度,并进行判断是否记录,最后右移右指针进行下次循环。


消消乐游戏


// 解题思路
// 1、将数据分割为字符放入list集合中,list可以删除对应数据,并及时更新,以便后续继续处理

// 2、根据每次消除完数据都要从头开始遍历,我们给定一个变量n表示list数据长度,遍历一次n就-1,当n=0代表遍历完成,也就代表字符串无法继续消除,此时list的长度就是最终值

  function delStr(s) {
            let list = [];
            let isFuhe = true;  //是否符合题意,只有大小写字母
            var reg = /^[A-Za-z]+$/; //字母正则

            for (let i = 0; i < s.length; i++) {
                let temp = s.charAt(i);
                if (!reg.test(temp)) {
                    isFuhe = false;
                    break;
                }
                list.push(temp);  //用list容器,因为list能及时更新数据
            }
            let n = s.length; //list数组中所剩处理数据

            while (n > 0 && isFuhe) {    //当所有数据处理完就退出
                n = list.length - 1;  //因为从第二个数据开始处理,所以做了-1处理
                for (let i = 1; i < list.length; i++) {
                    n--;    //处理一次,所剩数据-1
                    if (list[i] == list[i - 1]) { //有相同的字符进行清除
                        list.splice(i, 1);
                        list.splice(i - 1, 1);
                        break;  //list数据进行处理,处理完直接退出本次循环,重新开始新的循环
                    }
                }
            }
            return isFuhe ? list.length : 0
        }

【华为OD机试真题 JS】判断字符串子序列


// 解题思路
// 因为是求最后一个子串的第一个字母下标,所以我们从后面向前开始遍历

// 将target作为外部循环内容,从最后一个字符开始向前遍历。
// 将source作为内部循环内容,从最后一个字符开始向前遍历。
// 当source出现字符与target字符相同时,计数加一并记录其下标,将其作为下次遍历source初始的下标。接着是target的倒数第二字符。。。以此类推,直至target或source遍历完成
// 若计数等于target长度,则输出其下标

 function judge(target, source) {
      let n1 = target.length;
      let n2 = source.length;

      let n = 0;
      let res = n2;

      for (let i = n1 - 1; i >= 0; i--) {
        for (let j = res - 1; j >= 0; j--) {
          if (target.charAt(i) == source.charAt(j)) {
            n++;
            res = j;
            break;
          }
        }
      }

      if (n == n1) {
        return res
      } else {
        return -1
      }
    }

整数对最小和

// 解题思路: 构造新数组存储另外两数组两两元素组队之和,之后对新数组由小到大升序排列,输出前k项之和即可!
function sum(nums1, nums2, k) {
      let arr1 = nums1.sort((a, b) => a - b);
      let arr2 = nums2.sort((a, b) => a - b);
      let n1 = arr1.length;
      let n2 = arr2.length;
      let n = n1 + n2;
      let res = [];
      for (let i = 0; i < n1; i++) {
        for (let j = 0; j < n2; j++) {
          res.push(arr1[i] + arr2[j]);
        }
      }
      console.log(res,'asdasdas')
      res.sort((a, b) => a - b);
      let sum = 0;
      for (let i = 0; i < k; i++) {
        sum += res[i];
      }
      console.log(sum);
      return sum
    }

    console.log(sum([3, 1, 1, 4], [3, 1, 2, 3], 2))

【按区间反转文章片段】

function test(s,start,end){
    let arr = s.split(' ')
    let qieArr = arr.splice(start,end-start+1)
    qieArr.reverse()
    arr.splice(start,0,...qieArr)
    let str = arr.join(' ')
    console.log(str);
}


最长连续方波信号

let res = "";
let temp = "";
let b = false;  //是否开始识别
let isFomat = true; //是否满足条件
if(s.charAt(0)=='0'){       //如果第一个为0,则从第一个开始识别
    temp ="0";
    b = true;
}
 
for(let i=1;i<s.length;i++){
    if(b){      //识别中
        if(s.charAt(i)==s.charAt(i-1)){     //此时的数等于前一个数
            if(s.charAt(i)=='0'){       //出现重复的0则出局
                if(temp.length>=3 && isFomat){        //如果都是0,且符合规则(不含连续1大于3个长度)
                    res = temp.length>res.length ? temp : res;      //取最长信号
                }
                temp = "0";     //容器重置
                isFomat = true;
            }else {
                temp += s.charAt(i);      //出现重复的1继续,不过已不符合要求(不含连续的1)
                isFomat = false;
            }
        }else {
            temp += s.charAt(i);      //无重复的值则继续
        }
    } else {
        if(s.charAt(i)=='0'){   //遇到0就开始识别
            temp = "0";
            b = true;
        }
    }
}
console.log(res);


数组拼接


let step = Number("3");
let m = Number("2");
let test = ["2,5,6,7,9,5,7","1,7,4,3,4"];
let lists = [];

for(let i=0; i<m; i++){
   //let strings = readline().split(",").map(Number);
   let strings = test[i].split(",").map(Number);
   lists.push(strings);  //将数组放入集合中
}

let res = "";
let n = 0;  //起始下标
let count = 0;  //取完数字的数组
while (count<m){    //当取完的数组数量小于m时进入循环
   for(let i=0; i<m; i++){
       let list = lists[i];
       if(n>list.length){  //当其实下标大于数组长度时退出本次循环
           continue;
       }
       let end = n + step; //结束位置下标
       if(end >= list.length){   //当结束位置下标大于等于数组长度时
           end = list.length;
           count++;    //取完数字数组数量+1
       }
       for(let j=n; j<end; j++){
           res += list[j] + ",";
       }
   }
   n+=step;    //起始位置下标变更(+step)
}

console.log(res.substring(0,res.length-1));

停车场车辆统计


let cars = readLine().split(",");
//let cars = "1,1,0,0,1,1,1,0,1".split(",");
 
let count = 0;  //1的个数
let res = 0;
 
for(let i=0;i<cars.length;i++){
    if(cars[i]=="1"){
        count++;
    }else{
        if(count!=0){   //只要1的数量不是0则记为1辆车
            res++;
            count = 0;
        }
        continue;
    }
    if(count==3 || i==cars.length-1){ //3个1为1辆卡车直接计数
        res++;
        count = 0;
    }
}
 
console.log(res);

乱序整数序列两数之和绝对值最小


let strings = readLine().split(" ").map(i=>parseInt(i));
//let nums = "-1 -3 7 5 11 15".split(" ").map(i=>parseInt(i));

let n = nums.length;
let min = Number.MAX_VALUE;
let num1 = 0;
let num2 = 0;

for(let i=0;i<n-1;i++){
   for(let j=i+1;j<n;j++){
       let a = nums[i];
       let b = nums[j];
       let count = Math.abs(a+b);
       min = Math.min(count, min);
       if(min==count){
           num1 = a;
           num2 = b;
       }
   }
}

console.log(num1+" "+num2+" "+min);

最大括号深度

// 输入
input = "((([]){(()(})}))"

// 记录括号的栈
let stack = []
// 标记:字符串是否合法
let flag = true
// 最大深度
let max = 0

// 循环遍历输入
for (const x of input) {
   if ((x === '(') || (x === '[') || (x === '{')) {
   	// 如果是左括号,就入栈,同时判断此时栈的深度,以更新最大深度
       stack.push(x)
       max = Math.max(max, stack.length)
       continue
   }

   if ((x === ')')) {
   	// 若遇到右括号,判断此时栈顶的括号与它是否匹配,匹配则继续,不匹配,输出0,结束
       if (stack.pop() === '(') {
           continue
       } else {
           console.log(0);
           flag = false
           break
       }
   }

   if ((x === ']')) {
       if (stack.pop() === '[') {
           continue
       } else {
           console.log(0);
           flag = false
           break
       }
   }

   if ((x === '}')) {
       if (stack.pop() === '{') {
           continue
       } else {
           console.log(0);
           flag = false
           break
       }
   }
}

// 若标记为true,代表匹配无误,且此时栈要为空,则输出最大深度,否则输出0,代表匹配不合法
if (flag) {
   if (stack.length === 0) {
       console.log(max);
   } else {
       console.log(0);
   }
}

打印任务排序



let strings = readLine().split(",").map(i=>parseInt(i));
//let strings = "9,3,5".split(",").map(i=>parseInt(i));
let len = strings.length;

let mask = [];
let list = [];

for(let i=0;i<len;i++){
   let num = strings[i];
   let temp = [];
   temp.push(i);    //使用下标方便最后获取执行顺序
   temp.push(num);
   mask.push(temp);
}

while (mask.length > 0){
   let first = mask[0][1];    //队列最前的任务
   let isDayin = true; //是否进行打印
   for (let l of mask){
       if(first<l[1]){ //如果发现队列中有大于最前的
           let temp = mask.shift();
           mask.push(temp); //将最前的移动到队列最后
           isDayin = false;
           break;
       }
   }
   if(isDayin){
       let dayin = mask.shift();
       list.push(dayin[0]);  //打印完就移除任务,并将任务下标添加到list
   }
}

let res = [];
for (let i=0;i<len;i++){
   res[list[i]] = i;   //list的值与下标进行交换就是所需要的结果
}

console.log(res.join(","));


【华为OD机试真题 JS】IPv4地址转换成整数


let strings = readLine().split("#");
//let strings = "100#101#1#5".split("#");
let len = strings.length;
let count = 0;
let isF = true;

if(len==4){
   for(let i=0;i<len;i++){
       let n = Number(strings[i]);
       if(i==0 && (n<1 || n>128)){ //第一节 1~128
           isF = false;
           break;
       }else if(n<0 || n>255){ //二、三、四节 0~255
           isF = false;
           break;
       }
       /**
        * 首先使用把IP地址分成4个数字: 128 199 231 44
        *
        * 把每个数字转换为2进制,如果转换后这个数字对应的二进制数不够8位,在左侧补0: 10000000 11000111 11100111 00101100
        */
       count += n<<(8*(3-i));
   }
}else {
   isF = false;
}

if(isF){
   console.log(count);
}else {
   console.log("invalid IP");


【华为OD机试真题 JS】日志排序


var linNum = Number(readLine());
//var linNum = Number("2");
var lists = [];

//var test = ["01:41:8.9","1:1:09.211"];

for(let i=0;i<linNum;i++){
   var list = [];
   var strings = readLine().replace(".",":").split(":");
   //var strings = test[i].replace(".",":").split(":");
   for(let j=0;j<strings.length;j++){
       list.push(strings[j]);
   }
   lists.push(list);
}

lists.sort((a,b)=>{
   if(Number(b[0])>Number(a[0])){
       return -1;
   }
   if(Number(b[0])<Number(a[0])){
       return 1;
   }
   if(Number(b[1])>Number(a[1])){
       return -1;
   }
   if(Number(b[1])<Number(a[1])){
       return 1;
   }
   if(Number(b[2])>Number(a[2])){
       return -1;
   }
   if(Number(b[2])<Number(a[2])){
       return 1;
   }
   if(Number(b[3])>Number(a[3])){
       return -1;
   }
   if(Number(b[3])<Number(a[3])){
       return 1;
   }
   return 1;
});

for(let i=0;i<linNum;i++){
   console.log(lists[i][0]+":"+
               lists[i][1]+":"+
               lists[i][2]+"."+
               lists[i][3]);
}

【华为OD机试真题 JS】寻找相同子串


let t = readLine();
let p = readLine();
// let t = "AVERDXIVYERDIAN";
// let p = "RDXI";
 
if(t.length>1000000){
    console.log("No");
}
 
if(p.length>t.length && p.length>10000){
    console.log("No");
}
 
console.log(t.indexOf(p) == -1? "No" : t.indexOf(p)+1);

【华为OD机试真题 JS】斗地主之顺子


let s = readLine().split(" ");
//let s = "2 9 J 10 3 4 K A 7 Q A 5 6".split(" ");
let len = s.length;
let list = [];
 
for(let i=0;i<len;i++){ //剔除2,转化A,J,Q,K
    switch (s[i]){
        case "J":
            list.push(11);
            break;
        case "Q":
            list.push(12);
            break;
        case "K":
            list.push(13);
            break;
        case "A":
            list.push(14);
            break;
        case "2":
            break;
        default:
            list.push(Number(s[i]));
    }
}
 
list.sort((a,b)=>{
    return a-b;
}); //从小到大排序方便取值2 9 J 10 2 3 4 K A 7 Q A 5 6
 
let ress = [];
 
let isA = false; //是否遍历完整个数组
 
while (!isA){
    let res = [];
    res.push(list[0]);   //放入第一个数字
    let count = 1;
    for(let i=1;i<list.length;i++){
        let x = list[i];    //  本次数字
        if(x==list[i-1]+1){ //符合严格递增
            count++;
            res.push(x);
        }else if(x==list[i-1] && i!=list.length-1){
            continue;   //本次数字等于前面一个数字且不是数组最后一位,则进入下次循环
        }
        if(x!=list[i-1]+1 || i==list.length-1){
            if(count>=5){   //符合顺子
                ress.push(res);
            }else if(i==list.length-1){   //整个数组遍历完全,直接退出
                isA = true;
                break;
            }
            for(let j=0;j<res.length;j++){
                for(let k=0;k<list.length;k++){
                    if(res[j] == list[k]){
                        list.splice(list.indexOf(list[k]),1); //剔除已经处理过的数字
                        break;
                    }
                }
            }
            if(list.length<5){  //集合剩余数字不满足成为顺子
                isA = true;
            }
            break;  //顺子已经提取,跳出本次循环
        }
    }
}
 
if(ress.length==0){
    console.log("No");
}else {
    for(let i=0;i<ress.length;i++){
        let stringRes = "";
        for(let j=0;j<ress[i].length;j++){
            switch (ress[i][j]){    //将A\J\Q\K还原
                case 11:
                    stringRes+="J";
                    break;
                case 12:
                    stringRes+="Q";
                    break;
                case 13:
                    stringRes+="K";
                    break;
                case 14:
                    stringRes+="A";
                    break;
                default:
                    stringRes+=ress[i][j];
            }
            if(j<ress[i].length-1){
                stringRes+=" ";
            }
        }
        console.log(stringRes);
    }


【华为OD机试真题 JS】统计射击比赛成绩


let n = Number(readLine());
let s1 = readLine().split(","); //队员
let s2 = readLine().split(","); //射击成绩
 
// let n = Number("13");
// let s1 = "3,3,7,4,4,4,4,7,7,3,5,5,5".split(","); //队员
// let s2 = "53,80,68,24,39,76,66,16,100,55,53,80,55".split(","); //射击成绩
 
let map = {}    //将队员和射击成绩放入map对象中
 
/**
 * 队员作为key值,成绩作为value值(集合)
 */
for(let i=0;i<n;i++){
    let key = Number(s1[i]);
    let value = Number(s2[i]);
    if(map[key]){
        map[key].push(value);
    }else {
        let list = [];
        list.push(value);
        map[key] = list;
    }
}
/**
 * 将队员id及最高三个成绩之和放入集合list
 */
var scoreLists = [];
 
for(var key in map){
    let len = map[key].length;
    if(len>=3){
        let list = [];  //将所有队员数据放在集合scoreLists
        map[key].sort();    //对成绩进行排序并计算三个最高成绩和
        list.push(key);
        list.push(map[key][len-1] + map[key][len-2] + map[key][len-3]);
        scoreLists.push(list);
    }
}
 
scoreLists.sort((a,b)=>{
    if(b[1]>a[1]){  //成绩高的在前
        return 1;
    }
    if(b[1]==a[1] && b[0]>a[0]){  //成绩相等时,id高的在前
        return 1;
    }
    return -1;
});
 
let res = "";
let scoListsLen = scoreLists.length;
for(let i=0;i < scoListsLen - 1;i++){
    res+=scoreLists[i][0]+",";   //各队员成绩的第一个数为其id
}
console.log(res+scoreLists[scoListsLen-1][0]);

【华为OD机试真题 JS】喊7的次数重排

let s = sc.radLine().split(" ").map(i=>parseInt(i));;
//let s = "0 0 0 2 1".split(" ").map(i=>parseInt(i));
let len = s.length;
 
let ints = new Array(len).fill(0);
 
let num = 0;
for(let i=0;i<len;i++){
    num += s[i];     //计算出符合的次数
}
let step = 7;   //直接从7开始
while (num>0){
    if(step%7==0 || String(step).indexOf("7")!=-1){
        ints[(step-1)%len]++;      //同过数组长度算出符合的下标
        num--;      //符合的次数递减
    }
    step++;     //报数的次数递增
}
 
let res = "";
for(let i=0;i<len;i++){
    res+=String(ints[i]);
    if(i == len-1){
        break;
    }
    res+=" ";
}
 
console.log(res);

【华为OD机试真题 JS】最大矩阵和

let n = Number(readLine());   //行
let m = Number(readLine());   //列
//let n = Number("3");   //行
//let m = Number("4");   //列
 
//let test = ["-3,5,-1,5","2,4,-2,4","-1,3,-1,3"];
 
let ints = [];
 
for(let i=0;i<n;i++){
    //let input = readLine().split(",").map(i=>parseInt(i));
    let input = test[i].split(",").map(i=>parseInt(i));
    let hang = [];
    for(let j=0;j<m;j++){
        hang[j] = input[j];
    }
    ints[i] = hang;
}
 
let max = 0;
for(let start_row = 0;start_row<n;start_row++){   //开始行
    for(let start_col = 0;start_col<m;start_col++){   //开始列
        for(let end_row = start_row;end_row<n;end_row++){   //结束行
            let jisuan = 0; //矩阵和
            for(let end_col = start_col;end_col<m;end_col++){   //结束列
                let rowindex = end_row; //将结束行作为边界
                while (rowindex>=start_row){    //最后一行不能超过开始行
                    jisuan+=ints[rowindex][end_col];    //从结束行向上遍历到开始行
                    rowindex--;
                }
                max = Math.max(max,jisuan);
            }
        }
    }
}
 
console.log(max);

【华为OD机试真题 JS】分班


//let strings = readline().split(" ");
let strings = "6/N 8/Y 6/N 10/Y".split(" ");
 
let list1 = [];  //一班
let list2 = [];  //二班
 
let b = true;   //用来转换班级 true为一班 false为二班
let isError = false;
let isDigit = new RegExp("^[0-9]*$")
 
for(let i=0; i<strings.length; i++){
    let x = strings[i].split("/");
    if(!isDigit.test(x[0])){
        isError = true;
        break;
    }
    let stu = Number(x[0]);
    if((x[1] != "N" && x[1] != ("Y"))
        || list1.includes(stu)
        || list2.includes(stu))
    {
        isError = true;
        break;
    }
    if(list1.length == 0){    //第一位直接安排一班
        list1.push(stu);
        continue;
    }
    if(b){  //此时是一班
        if(x[1] == "N"){
            list2.push(stu) ;   //非一班
            b = false;
        }else {
            list1.push(stu);
        }
    } else {    //此时是二班
        if(x[1] == "N"){
            list1.push(stu);   //非二班
            b = true;
        }else {
            list2.push(stu);
        }
    }
 
}
 
if(isError){
    console.log("ERROR");
}else {
    list1.sort((a,b) =>{return a-b});
    list2.sort((a,b) =>{return a-b});
    let res1 = "";
    let res2 = "";
    for(let i=0; i<list1.length; i++){
        res1 += list1[i] + " ";
    }
    for(let i=0; i<list2.length; i++){
        res2 += list2[i] + " ";
    }
    if(list2.length == 0){
        console.log(res1.substring(0, res1.length-1));
    }else if(list1[0] < list2[0]){
        console.log(res1.substring(0, res1.length-1));
        console.log(res2.substring(0, res2.length-1));
    }else {
        console.log(res2.substring(0, res2.length-1));
        console.log(res1.substring(0, res1.length-1));
    }
}

素数之积

let n = Number(readLine());
//let n = Number("15");
 
let list = [];
let m = 0;
/**
 * 本题就是求出一个数只有两个因子(1不是素数)
 * 遍历n求出它所有的因子
 */
while (m!=n){   //当n==m时说明已经不能再除了,跳出循环
    n = m!=0? m: n;
    for(let i=2;i<Math.sqrt(n)+1;i++){
        if(n%i==0){
            m = n/i;    //把商作为下次的被除数
            list.push(i);    //i就是因子
            break;
        }
    }
}
 
list.push(m);
 
if(list.length==2){
    console.log(list[0]+" "+list[1]);
}else {
    console.log("-1 -1");
}

【华为OD机试真题 JS】字符串分割


var fuhe = 0; //能够实现的方案个数
var zichuan = 1;  //分割出的子串个数
 
let str = readLine();
//let str = "abc";
let res = 0;
 
fenge(str,n);
 
if(fuhe==1){
    res = zichuan;  //只有一种情况符合
}else if(fuhe>1){
    res = -1;   //大于一种情况符合
}
 
console.log(res);
 
function fenge(s, n){
 
    let len = s.length;
    let count = 0;  //ACSII码计数和
    for(let i=0;i<len;i++){
        count+=s.charCodeAt(i);
        if(count>999){  //大于999之后都不符合要求,直接退出
            break;
        }
        if( count>=100 && count<=999){  //水仙数[100,999]之间
            if(isSXS(count)){
                if(i==len-1){
                    fuhe++; //字符串遍历到最后一位都符合水仙数,说明是符合要求的
                    zichuan = ++n;
                }else {
                    let nums = n;
                    fenge(s.substring(i+1), ++nums); //将剩下的字符继续遍历
                }
            }
        }
    }
}
 
function isSXS(i){
 
    let b = parseInt(i/100);  //百位数
    let s = parseInt(i%100/10);   //十位数
    let g = i%100%10;   //个位数
 
    let count = (Math.pow(b,3) + Math.pow(s,3) + Math.pow(g,3));
 
    if(count == i){
        return true;
    }
 
    return false;
}

【华为OD机试真题 JS】数组连续和

let n = Number(readLine());
let x = Number(readLine());
let ints = readLine().split(" ");
 
// let n = Number("3");
// let x = Number("7");
// let ints = "3 4 7".split(" ");
 
let count;  //连续正数和
let res = 0;
 
for(let i=0;i<n;i++){
    count = Number(ints[i]);    //当前数字
    /**
     * 因为是正整数,所以如果当前数字符合要求
     * 则由此往后的连续和都符合要求
     * 连续区间数为长度n-当前数字下标i
     */
    if(count>=x){
        res+=n-i;
        break;
    }
    for (let j=i+1;j<n;j++){
        count+=Number(ints[j]);
        if(count>=x){
            res+=n-j;
            break;
        }
    }
}
console.log(res);

【华为OD机试真题 JS】拼接URL


let s = readLine().split(",");
//let s = ",/abc".split(",");

let res = "";

for(let i=0;i<s.length;i++){
   if(s[i]!="" && s[i]!="/"){
       /**
       * 将字符串中的"/"直接去除
       */
       res+="/"+s[i].replace("/","");
   }
}

console.log(res=="" ? "/" : res);

【华为OD机试真题 JS】转骰子

let s = readLine();
//let s = "FCR";

let res = "123456";  //骰子的初始状态

for(let i=0;i<s.length;i++){
   res = zhuanSZ(s.charAt(i),res);
}

console.log(res);

function zhuanSZ(s, sz){

   let s1 = sz.charAt(0);
   let s2 = sz.charAt(1);
   let s3 = sz.charAt(2);
   let s4 = sz.charAt(3);
   let s5 = sz.charAt(4);
   let s6 = sz.charAt(5);

   /**
    * 骰子转向各个方向的重新排序
    */
   switch (s){
       case "L":
           return s5+s6+s3+s4+s2+s1;
       case "R":
           return s6+s5+s3+s4+s1+s2;
       case "F":
           return s1+s2+s5+s6+s4+s3;
       case "B":
           return s1+s2+s6+s5+s3+s4;
       case "A":
           return s4+s3+s1+s2+s5+s6;
       case "C":
           return s3+s4+s2+s1+s5+s6;
   }
   return "";
}

【华为OD机试真题 JS】分糖果


var list = [];
let n = Number(readLine());
//let n = Number("15");

fentangguo(n,0);    //第一个参数糖果数量,第二个参数是次数(初始化为0)

list.sort((a,b)=>{  //从小到大排序
   if(b>a){
       return -1;
   }
   return 1;
});

console.log(list[0]);

function fentangguo(n,m){

   if (n==1) {
       list.push(m);    //只剩一个分糖完毕
       return 1;
   }
   if(n%2==0){
       m++;    //分一次次数加1
       fentangguo(n/2,m);
   }else{
       m++;    //放回或取出次数加1
       fentangguo(n-1,m);
       fentangguo(n+1,m);
   }
   return 0;
}

【华为OD机试真题 JS】找终点

let nums = readLine().split(" ").map(i=>parseInt(i));
//let nums = "7 5 9 4 2 6 8 3 5 4 3 9".split(" ").map(i=>parseInt(i));

let ints = [];
let len = nums.length;

for(let i=0;i<len;i++){
   ints[i] = nums[i];
}

let step = 0;   //步数的进度(数组下标)
let count = 0;  //步数
let x = Number.MAX_VALUE;
for(let i=0;i<len/2-1;i++){ //从第一个元素开始,第一步<length/2(下标为0,所以要减一)
   step = i;
   count = 1;
   while (step < len-1) {  //没有走完就需要继续
       step += ints[step];
       count++;
   }
   if(step == len-1){  //正好走完,比较步数
       x = Math.min(x,count);
   }
}
if(x==Number.MAX_VALUE){
   console.log("-1");
}else {
   console.log(x);
}

【华为OD机试真题 JS】服务器广播


let input = readline().split(" ").map(Number);
//let input = "1 1 0 0".split(" ").map(Number);

let n = input.length;   //确定是n阶数组
var list = []; //服务器连通对集合

for(let i=0; i<n; i++){
   if(input[i] == 1){   //说明两个服务器相连
       let temp = [];
       temp.push(1);
       temp.push(i+1);
       list.push(temp);
   }
}

//let test = ["1 1 0 0","1 1 0 1","0 0 1 1","0 1 1 1"];
for(let i=1; i<n; i++){
   input = readline().split(" ").map(Number);
   //input = test[i].split(" ").map(Number);
   for(let j=0; j<n; j++){
       if(input[j]==1 && j>=i){    //两个服务器相连,剔除冗余数据
           let temp = [];
           temp.push(i+1);
           temp.push(j+1);
           list.push(temp);
       }
   }
}

let res = 0;
while (list.length>0){
   let temp = list[0];
   list.splice(0,1);
   connectNet(temp);
   res++;
}

console.log(res);

/**
*
* @param intList   相连的服务器集合(集合中的所有服务器都可以进行通信)
*/
function connectNet(intList){
   for(let i=0; i<list.length; i++){
       let temp = list[i];
       let a = temp[0];
       let b = temp[1];
       if(intList.includes(a) || intList.includes(b)){
           temp.forEach(element => {
               if(!intList.includes(element)){
                   intList.push(element);
               }
           });
           list.splice(i,1);
           connectNet(intList);
       }
   }
}

【华为OD机试真题 JS】打印任务排序


let strings = readLine().split(",").map(i=>parseInt(i));
//let strings = "9,3,5".split(",").map(i=>parseInt(i));
let len = strings.length;

let mask = [];
let list = [];

for(let i=0;i<len;i++){
   let num = strings[i];
   let temp = [];
   temp.push(i);    //使用下标方便最后获取执行顺序
   temp.push(num);
   mask.push(temp);
}

while (mask.length>0){
   let first = mask[0][1];    //队列最前的任务
   let isDayin = true; //是否进行打印
   for (let l of mask){
       if(first<l[1]){ //如果发现队列中有大于最前的
           let temp = mask.shift();
           mask.push(temp); //将最前的移动到队列最后
           isDayin = false;
           break;
       }
   }
   if(isDayin){
       let dayin = mask.shift();
       list.push(dayin[0]);  //打印完就移除任务,并将任务下标添加到list
   }
}

let res = [];
for (let i=0;i<len;i++){
   res[list[i]] = i;   //list的值与下标进行交换就是所需要的结果
}

console.log(res.join(","))

停车场车辆统计


let cars = readLine().split(",");
//let cars = "1,1,0,0,1,1,1,0,1".split(",");

let count = 0;  //1的个数
let res = 0;

for(let i=0;i<cars.length;i++){
   if(cars[i]=="1"){
       count++;
   }else{
       if(count!=0){   //只要1的数量不是0则记为1辆车
           res++;
           count = 0;
       }
       continue;
   }
   if(count==3 || i==cars.length-1){ //3个1为1辆卡车直接计数
       res++;
       count = 0;
   }
}
console.log(res);

【华为OD机试真题 JS】相对开音节


let s = readLine().split(" ");
//let s = "ekam a ekac".split(" ");

let len = s.length;
let count = 0;

let reg = new RegExp("^[a-zA-Z]+$");    //全部英文的正则
for(let i=0;i<len;i++){
   let str = s[i];
   let strLen = str.length; //当前字符串长度
   if(strLen<4){    //字符串小于4不符合
       continue;
   }
   if(reg.test(str)){
       str = str.split("").reverse().join("");  //全英文则反转
   }
   for(let j=0;j<=strLen-4;j++){
       if(isKYJ(str.substring(j,j+4))){
           count++;
       }
   }
}

console.log(count);

function isKYJ(str){

   let yuanyin = "aeiou";
   let fuyin = "bcdfghjklmnpqrstvwxyz";

   let s1 = str[0];
   let s2 = str[1];
   let s3 = str[2];
   let s4 = str[3];

   if(fuyin.indexOf(s1)!=-1    //非元音即辅音
           && yuanyin.indexOf(s2)!=-1
           && fuyin.indexOf(s3)!=-1 && s3!="r"
           && s4=="e") {
       return true;
   }
   return false;
}

【华为OD机试真题 JS】信道分配


let R = Number(readLine());
let nInput = readLine().split(" ").map(i=>parseInt(i));

// let R = Number("5");
// let nInput = "10 5 0 1 3 2".split(" ").map(i=>parseInt(i));

let N = [];
for(let i=0;i<=R;i++){
   N[i] = nInput[i];
}

let D = Number(readLine());
//let D = Number("30");
let list = [];

let res = 0;    //支持用户数量
for(let i=0;i<=R;i++){
   for(let j=0;j<N[i];j++){
       let num = Math.pow(2,i);  //信道容量
       if(num>=D){ //信道容量大于用户需求时直接满足
           res++;
           continue;
       }
       list.push(num);
   }
}

let isEnough = true;    //是否够一个用户使用
while (isEnough){
   let count = list[list.length-1];    //取最大的信道
   list.splice(list.length-1,1); //取完需要剔除
   while (count<D && isEnough){
       let min = Number.MAX_VALUE;
       let minindex = 0;
       let temp = 0;
       for(let i = 0;i<list.length;i++){
           temp+=list[i];
           let chazhi =  Math.abs(D-count-list[i]);    //求出与所需信道最接近的信道
           min = Math.min(min, chazhi);
           if(min == chazhi){
               minindex = i;
           }
       }
       count+=list[minindex];
       list.splice(minindex,1);
       if(count>=D){
           res++;
           break;
       }
       if(count+temp<D){   //总共的信道不够一个用户使用
           isEnough = false;
       }
   }
}
console.log(res);

【华为OD机试真题 JS】太阳能板最大面积


let strings = readLine().split(",");
//let strings ="10,9,8,7,6,5,4,3,2,1".split(",");
let num = [];   //将输入放入整数数组中

for(let m=0;m<strings.length;m++){
   num[m] = Number(strings[m]);
}

let max = 0;    //最大面积

for(let n=1;n<num.length;n++){
   let min = num[n]; //假设当前挡板为最小挡板
   let temp = n-1; //前一个挡板下标
   for(let i=1;i<=n;i++){
       /**
        * 循环计算当前挡板到前面i个挡板的面积并求出最大值
        */
       min = Math.min(min,num[temp--]);   //min 求出前挡板到前面i个挡板最小高度
       max = Math.max(min*i,max);  //min*i 求出前挡板到前面i个挡板的面积
   }
}

console.log(max);

【华为OD机试真题 JS】连续字母长度

let s = readLine();
let n = Number(readLine());
// let s = "AABAAA";
// let n = Number("2");

let map = {};
let count = 1;    //相同字符的个数
for(let i=0;i<s.length-1;i++){
   if(s.charAt(i)==s.charAt(i+1)){ //当前字符跟后面一个字符比较,所以边界为s.length()-1
       count++;   //相同字符计数加1
   } else {
       if(map[s.charAt(i)]){
           count = Math.max(count,map[s.charAt(i)]);    //同字符长度取最长长度
       }
       map[s.charAt(i)] = count;
       count = 1;
   }
   if(i==s.length-2){    //最后一个字符
       let key = count==1 ? s.charAt(i+1) : s.charAt(i);
       map[key] = count;
   }
}

let list = [];    //长度(value)集合

for (let c in map
       ) {
   list.push(map[c]);
}

list.sort((a,b)=>{    //根据长度降序处理
   if (b>a){
       return 1;
   }
   return -1;
});

if(list.length>=n){
   console.log(list[n-1]);
}else {
   console.log(-1);
}

【华为OD机试真题 JS】矩阵最大值


let n = Number(readLine());
//let n = Number("5");
let res = 0;

// let test = ["1,0,0,0,1",
//             "0,0,0,1,1",
//             "0,1,0,1,0",
//             "1,0,0,1,1",
//             "1,0,1,0,1"]

for(let i=0;i<n;i++){
   let s = readLine().replaceAll(",","");   //直接将输入值转换为字符串
   //let s = test[i].replaceAll(",","");
   let max = 0;
   for(let j=0;j<n;j++){
       let newS = s.substring(j) + s.substring(0,j); //字符串分段拼接相当于右移
       max = Math.max(max,parseInt(newS,2));
   }
   res+=max;
}
console.log(res);

【华为OD机试真题 JS】判断字符串子序列


let target = readLine();
let source = readLine();
// let target = "abc";
// let source = "abcaybec";

let n1 = target.length;
let n2 = source.length;

let n = 0;
let res = n2;

for(let i=n1-1;i>=0;i--){
   for(let j=res-1;j>=0;j--){
       if(target.charAt(i)==source.charAt(j)){
           n++;
           res = j;
           break;
       }
   }
}

if(n==n1){
   console.log(res);
}else {
   console.log(-1);
}

【华为OD机试真题 JS】解压报文


let s = readLine();
//let s = "3[m2[c]]";
let res = "";  //处理前的字母串
let numStr = "";  //处理多位数
let num = [];    //数字队列
let zimu = [];  //放置处理后的字母串
for(let i=0;i<s.length;i++){
   let c = s.charAt(i);
   if(!isNaN(Number(c))){  //判断是否为数字
       if(res.length!=0){    //数字前的字母暂不处理
           zimu.push(res);
           res = "";
       }
       numStr += c;
   }else if(c=='['){
       num.push(Number(numStr));  //数字放入数字队列
       numStr = "";
   }else if(c==']'){
       let n = num.pop();  //碰到“]”,就需要取出最上面的数字进行解压
       if(res.length!=0){
           zimu.push(res);
           res = "";
       }
       let temp = zimu.pop(); //取出最上面的字母
       let sb = "";
       for(let j=0;j<n;j++){
           sb+=temp;    //对字母进行解压
       }
       if(zimu.length==0){
           zimu.push(sb);
       }else {
           zimu.push(zimu.pop()+sb);   //后面处理过的字符会跟最上面的字符一起被处理
       }
   }else {
       res+=c;
   }
}
console.log(zimu);

【华为OD机试真题 JS】报数游戏


let n = Number(readLine());

//let n = Number("3");

let list = [];

for(let i=1;i<=100;i++){
   list.push(i);    //100个人的集合
}

let i=n-1;  //初始下标(集合下标从0开始,所有要-1)

while (list.length>=n){ //如果人数大于等于n就需要继续
       list.splice(i,1); //移除报n的人
       i--;    //因为少了一个人所以后面的所有下标都要向前移一位
       i = i+n<list.length ? i+n : i+n-list.length;  //因为是围成的圆圈,所以下标越界后需要绕到最前面
}

console.log(list);