【华为OD机考 统一考试机试C卷】 - JS篇

1. 字符串序列判定/最后一个有效字符

const readline = require('readline');

// 创建一个readline接口对象来读取用户的输入
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

// 读取第一个字符串S
rl.on('line', (stringS) => {
  // 读取第二个字符串L
  rl.on('line', (stringL) => {
    // 初始化两个索引,分别用于遍历S和L
    let indexS = 0;
    let indexL = 0;

    // 当S和L都没有遍历完时,继续遍历
    while (indexS < stringS.length && indexL < stringL.length) {
      // 如果S中的当前字符与L中的当前字符相同,则S的索引加1
      if (stringS.charAt(indexS) === stringL.charAt(indexL)) {
        indexS++;
      }
      // 无论字符是否相同,L的索引都加1
      indexL++;
    }

    // 如果S的所有字符都在L中找到了(即S已经遍历完了),则打印L中最后一个有效字符的位置(即L的当前索引减1)
    if (indexS === stringS.length) console.log(indexL - 1);
    // 如果S还有字符没有在L中找到,则打印-1
    else console.log(-1);

    rl.close();
  });
});

2.山脉个数(逻辑)

function count_peaks(hill_map) {
    let count = 0; // 初始化计数器为 0
    for(let i = 0; i < hill_map.length; i++){ // 遍历数组 hill_map
        if(i === 0 && hill_map[i] > hill_map[i+1]){ // 如果当前位置在数组的开头,并且当前元素大于下一个元素
            count++; // 计数器加一
        }
        if(i === hill_map.length-1 && hill_map[i] > hill_map[i-1]){ // 如果当前位置在数组的末尾,并且当前元素大于前一个元素
            count++; // 计数器加一
        }
        if(i > 0 && i < hill_map.length-1 && hill_map[i] > hill_map[i-1] && hill_map[i] > hill_map[i+1]){ // 如果当前位置不在开头和末尾,并且当前元素大于前一个元素且大于后一个元素
            count++; // 计数器加一
        }
        
    }
    return count; // 返回计数器的值作为结果
}

3.构成指定长度的字符串的个数(去重排组合)

// 导入所需的模块
const readline = require('readline');

// 创建一个接口来读取用户的输入
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

// 递归生成满足条件的不同字符串
function generateDistinctStrings(str, length, current, set, used) {
  // 当生成的字符串长度等于指定长度时,将其加入到集合中
  if (current.length === length) {
    set.add(current);
    return;
  }

  // 遍历字符串中的字符
  for (let i = 0; i < str.length; i++) {
    // 判断字符是否已经被使用,或者当前字符与前一个字符相同
    if (used[i] || (current.length > 0 && current.charAt(current.length - 1) === str.charAt(i))) {
      continue; // 如果字符已被使用或与前一个字符相同,则跳过当前字符
    }
    used[i] = true; // 标记当前字符为已使用
    // 递归调用生成下一个字符
    generateDistinctStrings(str, length, current + str.charAt(i), set, used);
    used[i] = false; // 取消标记当前字符的使用状态,以便下一次遍历
  }
}

// 计算满足条件的不同字符串的数量
function countDistinctStrings(str, length) {
  // 创建一个集合来存储不同的字符串
  const set = new Set();
  // 创建一个数组来标记字符串中的字符是否已经被使用
  const used = new Array(str.length).fill(false);
  // 调用generateDistinctStrings方法生成满足条件的不同字符串
  generateDistinctStrings(str, length, "", set, used);
  // 打印生成的所有不同的字符串
  // for (let string of set) {
    // console.log(string);
  // }
  // 返回不同字符串的数量
  return set.size;
}

// 读取用户输入的字符串
rl.on('line', (input) => {
  // 将输入的字符串按空格分割为两部分,分别为字符串和长度
  const parts = input.split(" ");
  const str = parts[0]; // 获取输入的字符串
  const length = parseInt(parts[1]); // 将输入的长度部分转换为整数

  // 调用countDistinctStrings方法计算满足条件的不同字符串的数量
  const count = countDistinctStrings(str, length);
  // 输出计算结果
  console.log(count);

  rl.close();
});

4.用连续自然数之和来表达整数(滑动窗口)

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

// 提示用户输入目标整数
rl.on('line', (target) => {
  target = parseInt(target);  // 将输入的字符串转换为整数
  console.log(`${target}=${target}`);
  
  let expressions = [];  // 存储所有满足条件的表达式

  // 遍历所有可能的起始自然数
  for (let i = 1; i < target; i++) {
    let sum = 0;
    let expression = '';

    // 从i开始累加,直到sum大于或等于target
    for (let j = i; sum < target; j++) {
      sum += j;
      expression += `${j}+`;  // 向表达式中添加自然数和加号

      // 当累加和等于目标整数时,将表达式存储到数组中
      if (sum === target) {
        expressions.push(expression.slice(0, -1));  // 去掉表达式末尾的加号
        break;
      }
    }
  }

  // 自定义比较函数,用于按表达式中自然数的个数进行排序
  expressions.sort((a, b) => {
    let aCount = a.split('+').length;
    let bCount = b.split('+').length;
    return aCount - bCount;
  });

  // 输出所有满足条件的表达式
  expressions.forEach(expression => {
    console.log(`${target}=${expression}`);
  });

  // 输出满足条件的表达式个数
  console.log(`Result: ${expressions.length + 1}`);

  rl.close();
});

5.全量和已占用字符集、字符串统计(逻辑)


const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.on('line', (input) => {
  // 将输入字符串按照@符号分割为全量字符集和已占用字符集
  const splitInput = input.split("@");
  const fullCharacterSet = splitInput[0]; // 全量字符集
  const occupiedCharacterSet = splitInput[1]; // 已占用字符集

  // 创建字符列表,用于存储全量字符集中的字符及其对应的数量
  const characterList = [];

  // 将全量字符集按照逗号分割为单个字符
  const fullCharacterSetSplit = fullCharacterSet.split(",");

  // 遍历全量字符集的每个字符
  for (const character of fullCharacterSetSplit) {
    // 将字符按照冒号分割为字符和数量
    const characterSplit = character.split(":");
    characterList.push(characterSplit); // 将字符和数量添加到字符列表中
  }

  // 如果已占用字符集为空,则输出全量字符集
  if (occupiedCharacterSet === "") {
    console.log(fullCharacterSet + "@");
    process.exit(0);
  }

  // 创建已占用字符集的哈希表,用于存储已占用字符及其对应的数量
  const occupiedCharacters = {};

  // 将已占用字符集按照逗号分割为单个字符
  const occupiedCharacterSetSplit = occupiedCharacterSet.split(",");

  // 遍历已占用字符集的每个字符
  for (const character of occupiedCharacterSetSplit) {
    // 将字符按照冒号分割为字符和数量
    const characterSplit = character.split(":");
    occupiedCharacters[characterSplit[0]] = parseInt(characterSplit[1]); // 将字符和数量添加到已占用字符集的哈希表中
  }

  // 遍历字符列表中的每个字符
  for (let i = 0; i < characterList.length; i++) {
    const character = characterList[i];
    // 如果已占用字符集中包含当前字符
    if (character[0] in occupiedCharacters) {
      const count = parseInt(character[1]) - occupiedCharacters[character[0]]; // 计算剩余可用数量
      if (count > 0) {
        character[1] = count.toString(); // 更新字符列表中的数量为剩余可用数量
      } else {
        characterList.splice(i, 1); // 如果剩余可用数量为0,则移除当前字符
        i--; // 由于移除了一个字符,需要将索引减1
      }
    }
  }

  // 构建输出字符串
  let result = "";
  for (const character of characterList) {
    result += character[0] + ":" + character[1] + ","; // 将每个字符及其数量添加到输出字符串中
  }
  result = result.slice(0, -1); // 删除最后一个逗号
  console.log(result); // 输出结果

  rl.close();
});

6.密码输入检测(逻辑)

const readline = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
});

readline.on('line', input => {
  let result = '';
  let isBig = false;
  let isSmall = false;
  let isNum = false;
  let isSpec = false;

  for (let c of input) {
    if (c === '<') {
      result = result.slice(0, -1);
    } else {
      result += c;
    }
  }

  for (let c of result) {
    if (/[0-9]/.test(c)) {
      isNum = true;
    } else if (/[a-z]/.test(c)) {
      isSmall = true;
    } else if (/[A-Z]/.test(c)) {
      isBig = true;
    } else {
      isSpec = true;
    }
  }

  let flagRes = result.length >= 8 && isNum && isSmall && isBig && isSpec;

  console.log(result + "," + flagRes);

  readline.close();
});

7.查找众数及中位数(逻辑)

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.on('line', (input) => {
  const numbers = input.split(" ").map(num => parseInt(num));

  const countMap = new Map();
  let maxCount = 0;
  for (let number of numbers) {
    let count = countMap.get(number) || 0;
    count++;
    countMap.set(number, count);
    maxCount = Math.max(maxCount, count);
  }

  const maxCountNumbers = Array.from(countMap.entries())
    .filter(entry => entry[1] === maxCount)
    .map(entry => entry[0])
    .sort((a, b) =>b - a);

  let median;
  if (maxCountNumbers.length % 2 !== 0) {
    let index = Math.floor((maxCountNumbers.length + 1) / 2) - 1;
    median = maxCountNumbers[index];
  } else {
    let index1 = maxCountNumbers.length / 2 - 1;
    let index2 = maxCountNumbers.length / 2;
    median = Math.floor((maxCountNumbers[index1] + maxCountNumbers[index2]) / 2);
  }

  console.log(median);

  rl.close();
});

8.最长的指定瑕疵的元素子串(双指针)

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});
rl.on('line', (line) => {
  // 输入瑕疵度
  const flaw = parseInt(line.trim());
  // 输入字符串
  rl.on('line', (line) => {
     // 移除收尾空字符串
    const s = line.trim();
    // 定义元音字母集合
    const vowels = new Set(['a', 'e', 'i', 'o', 'u', 'A', 'E', 'I', 'O', 'U']);
    // 记录字符串中所有元音字母的下标
    const vowelIdxs = [];
    for (let i = 0; i < s.length; i++) {
      if (vowels.has(s.charAt(i))) {
        vowelIdxs.push(i);
      }
    }
    // 初始化双指针 
    let left = 0, right = 0 ;
    // 记录所有满足瑕疵度的元音子串的长度
    const lengths = [];
    while (right < vowelIdxs.length) {
      // 计算当前子串的瑕疵度
      const lengthDiff = vowelIdxs[right] - vowelIdxs[left] - (right - left);
      if (lengthDiff > flaw) {
        // 如果瑕疵度超过了预期,左指针右移
        left++;
      } else {
        // 如果瑕疵度不超过预期,记录子串长度
        if (lengthDiff === flaw) {
          lengths.push(vowelIdxs[right] - vowelIdxs[left] + 1);
        }
        // 右指针右移
        right++;
      }
    }
    // 如果没有满足瑕疵度的元音子串,输出 0
    if (lengths.length === 0) {
      console.log(0);
      return;
    }
    // 输出最长的元音子串的长度
    lengths.sort((a, b) => b - a);
    console.log(lengths[0]);
  });
});

9.整数最小和(逻辑)

/*
 * @Author: liwen liwen01@raxtone.com
 * @Date: 2024-04-02 14:19:20
 * @LastEditors: liwen liwen01@raxtone.com
 * @LastEditTime: 2024-04-02 14:21:13
 * @FilePath: \raxtone\Javasctipt\zhengshuzuixiaohe.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
const readline = require('readline');

// 创建readline接口实例
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

 rl.on('line', (array1Input) => {
  // 将输入的字符串按空格分割为数组,并将每个元素转换为数字,然后去除第一个元素
  const array1 = array1Input.split(' ').map(Number).slice(1);
   rl.on('line', (array2Input) => {
    // 将输入的字符串按空格分割为数组,并将每个元素转换为数字,然后去除第一个元素
    const array2 = array2Input.split(' ').map(Number).slice(1);

     rl.on('line', (kInput) => {
      // 将输入的字符串转换为整数
      const k = parseInt(kInput);

      // 创建一个空数组pairsSum
      const pairsSum = [];

      // 嵌套循环,将array1和array2中的元素两两相加,并将结果存储到pairsSum中
      for (const value1 of array1) {
        for (const value2 of array2) {
          pairsSum.push(value1 + value2);
        }
      }

      // 对pairsSum中的元素进行排序
      pairsSum.sort();

      // 取出pairsSum中前k个元素,并使用reduce方法计算它们的和
      const minSum = pairsSum.slice(0, k).reduce((sum, value) => sum + value, 0);

      // 输出最小和
      console.log(minSum);

      // 关闭readline接口,结束程序的执行
      rl.close();
    });
  });
});

10.找出作弊的人(排序比较)

const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];

rl.on('line', (line) => {
    input.push(line.trim());
}).on('close', () => {
    // 读取员工的数量
    const n = parseInt(input.shift());
    // 创建一个数组用于存储员工的ID和分数
    const employees = input.map(line => line.split(' ').map(Number));

    // 按分数排序
    employees.sort((a, b) => a[1] - b[1]);

    let minDiff = Number.MAX_SAFE_INTEGER;
    const pairs = [];

    for (let i = 0; i < n - 1; i++) {
        for (let j = i + 1; j < n; j++) {
            const curDiff = employees[j][1] - employees[i][1];
            if (curDiff < minDiff) {
                pairs.length = 0; // 清空数组
                minDiff = curDiff;
                pairs.push({ id1: Math.min(employees[i][0], employees[j][0]), id2: Math.max(employees[i][0], employees[j][0]) });
            } else if (curDiff === minDiff) {
                pairs.push({ id1: Math.min(employees[i][0], employees[j][0]), id2: Math.max(employees[i][0], employees[j][0]) });
            } else {
                break;
            }
        }
    }

    // 对ID对进行排序
    pairs.sort((a, b) => a.id1 - b.id1 || a.id2 - b.id2);

    // 输出结果
    pairs.forEach(pair => {
        console.log(`${pair.id1} ${pair.id2}`);
    });
});

 

11.找朋友(栈)


const readline = require('readline');
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

let n = 0;
let height = [];

rl.on('line', (input) => {
  if (!n) {
    n = parseInt(input.trim());
  } else {
    height = input.trim().split(' ').map(Number);
    
    let friendIndexes = new Array(n).fill(0);
    let stack = [0];
    for (let i = 1; i < n; i++) {
        while (stack.length && height[i] > height[stack[stack.length - 1]]) {
            friendIndexes[stack.pop()] = i;
        }
        stack.push(i);
    }
    
    let result = "";
    for (let i = 0; i < n; i++) {
        result += friendIndexes[i] + " ";
    }
    console.log(result.trim());
  }
});


12.爱吃蟠桃的孙悟空(二分法)

// 读取标准输入
const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

// 判断以速度k是否能在h小时内吃完所有桃子
function canFinish(p, h, k) {
    let ans = 0;
    for (let x of p) {
        ans += Math.ceil(x / k);
    }
    return ans <= h;
}

// 处理输入
rl.on('line', (input) => {
    if (!this.peachCounts) {
        // 第一行输入,转换为桃子数量数组
        this.peachCounts = input.split(' ').map(Number);
        return;
    }
    // 第二行输入,转换为小时数
    const h = Number(input);
    rl.close(); // 不再读取输入

    // 输入验证
    const n = this.peachCounts.length;
    if (n === 0 || h <= 0 || n >= 10000 || h >= 10000 || n > h) {
        console.log(0);
        return;
    }

    // 二分查找最小吃桃速度
    let left = 1, right = 1e9;
    while (left < right) {
        const mid = Math.floor((left + right) / 2);
        if (canFinish(this.peachCounts, h, mid)) {
            right = mid;
        } else {
            left = mid + 1;
        }
    }

    // 输出最小吃桃速度
    console.log(left);
});

13.游戏分组-王者荣耀(DFS)

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

let res = Number.MAX_SAFE_INTEGER;
let totalSum = 0;
let targetSum = 0;


// 深度优先搜索函数
function dfs(nums, idx, count, currentSum) {
    // 剪枝条件:如果当前总和超过目标,则停止 考友反馈,去掉可得100%
    // if (currentSum > targetSum) return;

    // 当我们为一个队伍选择了5名玩家时
    if (count === 5) {
        // 计算另一个队伍的总和
        let otherTeamSum = totalSum - currentSum;
        // 用较小的差值更新结果
        res = Math.min(res, Math.abs(currentSum - otherTeamSum));
        return;
    }

    // 如果我们已经考虑了所有玩家,停止递归
    if (idx === 10) return;

    // 为第一个队伍选择当前玩家
    dfs(nums, idx + 1, count + 1, currentSum + nums[idx]);
    
    // 不为第一个队伍选择当前玩家
    dfs(nums, idx + 1, count, currentSum);
}

rl.on('line', (input) => {
    let nums = input.split(' ').map(Number);
    for (let num of nums) {
        totalSum += num;
    }
    targetSum = totalSum / 2;
    dfs(nums, 0, 0, 0);
    console.log(res);
    rl.close();
});

14.求满足条件的最长子串的长度(滑动窗口)

const readline = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
});

// 读取输入的字符串
readline.on('line', (str) => {
  // 初始化最长子串长度为-1
  let maxLen = -1;
  // 初始化一个标志,表示是否找到了包含字母的子串
  let hasLetter = false;

  // 初始化双指针l和r,分别表示子串的左右边界
  let l = 0, r = 0;
  // 创建一个双端队列用于存储字母的索引
  let letterIdx = [];

  // 遍历字符串
  while (r < str.length) {
    // 获取当前字符
    let c = str.charAt(r);

    // 如果当前字符是字母
    if (c.match(/[a-zA-Z]/)) {
      // 设置标志为true,表示找到了包含字母的子串
      hasLetter = true;
      // 将字母的索引添加到队列的尾部
      letterIdx.push(r);

      // 如果队列中有多于1个字母的索引
      if (letterIdx.length > 1) {
        // 移除队列头部的字母索引,并将左指针l移动到该索引的下一个位置
        l = letterIdx.shift() + 1;
      }

      // 如果右指针r等于左指针l,跳过当前循环
      if (r === l) {
        r++;
        continue;
      }
    }

    // 更新最长子串长度
    maxLen = Math.max(maxLen, r - l + 1);
    // 移动右指针
    r++;
  }

  // 如果没有找到包含字母的子串,输出-1
  if (!hasLetter) {
    console.log(-1);
  } else {
    // 否则输出最长子串长度
    console.log(maxLen);
  }

  readline.close();
});

15. 分割均衡字符串(贪心)

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.on('line', (s) => {
  // 初始化变量,用于记录可分割成新的均衡子串的最大个数
  let ans = 0;
  // 初始化变量,用于记录当前位置字符'X'和'Y'的差值
  let count = 0;

  // 遍历字符串的每个字符
  for (let i = 0; i < s.length; i++) {
    // 判断当前字符是'X'还是'Y'
    if (s.charAt(i) === 'X') {
      // 如果是'X',则将count加1,表示出现了一个'X'
      count++;
    } else {
      // 如果是'Y',则将count减1,表示出现了一个'Y'
      count--;
    }

    // 在每次更新count后,判断count是否为0
    if (count === 0) {
      // 如果为0,表示当前位置可以作为分割点,将ans加1
      ans++;
    }
  }

  // 输出可分割成新的均衡子串的最大个数
  console.log(ans);

  rl.close();
});

16.机器人仓库搬砖(二分法)

function minEnergyBlocks(bricks, hours) {
    if (bricks.length > 8) { // 如果砖块数量大于8
        return -1; // 返回-1
    }
    let left = 1, right = Math.max(...bricks); // 初始化左右边界
    while (left < right) { // 二分查找
        let middle = Math.floor((left + right) / 2); // 取中间值
        let total_time = 0; // 计算当前能量块数量下能够搬完所有砖的总时间
        for (let i = 0; i < bricks.length; i++) {
            total_time += Math.ceil(bricks[i] / middle);
        }
        if (total_time > hours) { // 如果当前能量块数量下搬完所有砖的总时间超过了限定时间,缩小搜索范围
            left = middle + 1;
        } else { // 否则,减小能量块数量
            right = middle;
        }
    }
    let sum = 0;
    for (let i = 0; i < bricks.length; i++) {
        sum += Math.ceil(bricks[i] / left);
    }
    if (sum > hours) { // 检查最终确定的能量块数量是否能在规定时间内搬完所有砖
        return -1; // 无法在规定时间内搬完所有砖
    }
    return left; // 返回最小能量块数量
}

const readline = require('readline');
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.on('line', (input) => {
    const bricks = input.split(' ').map(Number);
    console.log(minEnergyBlocks(bricks, 8)); // 调用函数并输出结果
    rl.close();
});

17.出租车计费 、靠谱的车(逻辑)

const readline = require('readline');

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

rl.on('line', (line) => {
  let correct = 0;
  for (let i = 0; i < line.length; i++) {
    let digit = parseInt(line[i]);
    if (digit > 4) {
      digit--;
    }
    correct = correct * 9 + digit;
  }
  console.log(correct);
});

18.开源项目热度榜单

/*
 * @Author: liwen liwen01@raxtone.com
 * @Date: 2024-04-02 19:59:07
 * @LastEditors: liwen liwen01@raxtone.com
 * @LastEditTime: 2024-04-02 20:00:15
 * @FilePath: \raxtone\Javasctipt\openproject.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

// 创建一个数组用于存储用户的输入
let input = [];
// 当接收到一行输入时,将其去除首尾空格后添加到input数组中
rl.on('line', (line) => {
    input.push(line.trim());
}).on('close', () => { // 当输入结束时,执行以下代码
    // 读取项目数量n
    const n = parseInt(input[0]);
    // 读取权重数组,将其转换为数字数组
    const weights = input[1].split(' ').map(Number);

    // 创建一个数组用于存储项目信息
    let projects = [];
    // 读取每个项目的信息
    for (let i = 2; i < 2 + n; i++) {
        // 将项目信息分割为名称和评分数组
        const project = input[i].split(' ');
        const name = project[0];
        const scores = project.slice(1).map(Number);

        // 计算项目的热度
        let hotness = 0;
        for (let j = 0; j < 5; j++) {
            hotness += scores[j] * weights[j];
        }

        // 将项目的名称和热度添加到projects数组中
        projects.push({ name, hotness });
    }

    // 对项目数组进行排序,首先根据热度降序排序,如果热度相同则根据名称升序排序
    projects.sort((a, b) => {
        if (a.hotness !== b.hotness) {
            return b.hotness - a.hotness;
        } else {
            return a.name.localeCompare(b.name);
        }
    });

    // 遍历排序后的项目数组并打印项目名称
    for (let project of projects) {
        console.log(project.name);
    }
});

19.寻找身高相近的小朋友

const readline = require('readline');

// 创建readline接口,用于读取输入
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

let h, n;
let heights = [];

// 监听输入事件
rl.on('line', (input) => {
  // 如果h和n未赋值,表示当前输入为第一行,包含小明的身高和新班级其他小朋友的个数
  if (!h && !n) {
    const inputArr = input.split(' ');
    h = parseInt(inputArr[0]);
    n = parseInt(inputArr[1]);
  } else {
    // 否则,表示当前输入为第二行,包含其他小朋友的身高
    const heightArr = input.split(' ');
    // 将输入的身高字符串转换为整数并存储在heights数组中
    heights = heightArr.map(height => parseInt(height));
    // 对heights数组进行排序
    heights.sort((a, b) => {
      const diffA = Math.abs(a - h);
      const diffB = Math.abs(b - h);
      // 如果两个小朋友和小明身高差一样,则个子较小的小朋友排在前面
      if (diffA === diffB) {
        return a - b;
      }
      // 否则,根据与小明身高差的绝对值进行排序
      return diffA - diffB;
    });
    // 输出排序后的结果
    console.log(heights.join(' '));
  }
});

20.考勤信息(逻辑)

// 引入readline模块用于读取命令行输入
const readline = require('readline');

// 创建readline接口实例
const rl = readline.createInterface({
    input: process.stdin, // 标准输入流
    output: process.stdout // 标准输出流
});

// 定义函数判断是否能获得考勤奖
const canReceiveAward = (records) => {
    let absentCount = 0; // 缺勤次数计数器
    for (let i = 0; i < records.length; i++) {
        if (records[i] === 'absent') { // 如果记录为缺勤
            absentCount++; // 缺勤次数加1
            if (absentCount > 1) return false; // 缺勤超过1次,返回false
        }
        if (records[i] === 'late' || records[i] === 'leaveearly') { // 如果记录为迟到或早退
            // 如果前一天也是迟到或早退,返回false
            if (i > 0 && (records[i - 1] === 'late' || records[i - 1] === 'leaveearly')) {
                return false;
            }
        }
        if (i >= 6) { // 检查任意连续7天的考勤记录
            let countIn7Days = 0; // 连续7天内非正常上班的天数
            for (let j = i - 6; j <= i; j++) {
                if (records[j] !== 'present') { // 如果这7天内有非出勤记录
                    countIn7Days++;
                }
            }
            if (countIn7Days > 3) return false; // 如果连续7天内非正常上班超过3天,返回false
        }
    }
    return true; // 所有条件都满足,返回true
};

let lines = []; // 存储输入行的数组

// 监听命令行输入
rl.on('line', (line) => {
    lines.push(line); // 将每行输入存储到lines数组中
}).on('close', () => { // 输入结束时触发
    const testCases = parseInt(lines[0], 10); // 解析测试用例数量
    for (let i = 1; i <= testCases; i++) { // 遍历每个测试用例
        const attendanceRecords = lines[i].trim().split(" "); // 分割考勤记录
        // 输出每个测试用例的结果,并根据条件添加空格分隔
        process.stdout.write(canReceiveAward(attendanceRecords) ? "true" : "false");
        if (i < testCases) {
            process.stdout.write(" ");
        }
    }
    process.exit(0); // 执行完毕后退出程序
});

21.寻找身高相近的小朋友

const readline = require('readline');

// 创建readline接口,用于读取输入
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

let h, n;
let heights = [];

// 监听输入事件
rl.on('line', (input) => {
  // 如果h和n未赋值,表示当前输入为第一行,包含小明的身高和新班级其他小朋友的个数
  if (!h && !n) {
    const inputArr = input.split(' ');
    h = parseInt(inputArr[0]);
    n = parseInt(inputArr[1]);
  } else {
    // 否则,表示当前输入为第二行,包含其他小朋友的身高
    const heightArr = input.split(' ');
    // 将输入的身高字符串转换为整数并存储在heights数组中
    heights = heightArr.map(height => parseInt(height));
    // 对heights数组进行排序
    heights.sort((a, b) => {
      const diffA = Math.abs(a - h);
      const diffB = Math.abs(b - h);
      // 如果两个小朋友和小明身高差一样,则个子较小的小朋友排在前面
      if (diffA === diffB) {
        return a - b;
      }
      // 否则,根据与小明身高差的绝对值进行排序
      return diffA - diffB;
    });
    // 输出排序后的结果
    console.log(heights.join(' '));
  }
});

22.剩余银饰的重量

const readline = require('readline');

const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

// 创建一个数组 lines,用于存储用户输入的每一行
let lines = [];

// 当用户输入一行并按下回车键时,触发 'line' 事件
rl.on('line', (line) => {
    // 将用户输入的行添加到 lines 数组中
    lines.push(line);

    // 当 lines 数组中的行数等于 2 时,开始处理银饰的重量
    if (lines.length === 2) {
        // 从 lines 数组的第二行开始,将输入的银饰重量转换为数字,并存储在 silverPieces 数组中
        let silverPieces = lines[1].split(' ').map(Number);
        // 对 silverPieces 数组进行降序排序
        silverPieces.sort((a, b) => b - a);

        // 当 silverPieces 数组中至少有三块银饰时,执行循环
        while (silverPieces.length >= 3) {
            // 取出三块最重的银饰
            let z = silverPieces.shift();
            let y = silverPieces.shift();
            let x = silverPieces.shift();

            // 如果三块银饰的重量相同,则全部熔化,不剩余
            if (x === y && y === z) {
                continue;
            } else {
                let remaining; // 剩余银饰的重量
                // 如果有两块重量相同,且第三块更重,则剩余 z - y
                if (x === y && y < z) {
                    remaining = z - y;
                }
                // 如果有两块重量相同,且第一块更轻,则剩余 y - x
                else if (x < y && y === z) {
                    remaining = y - x;
                }
                // 如果三块银饰重量都不同,则计算剩余重量
                else {
                    remaining = Math.abs((z - y) - (y - x));
                }
                if (remaining !== 0) {
                    // 将剩余银饰的重量加入数组
                    silverPieces.push(remaining);
                }

                // 重新排序
                silverPieces.sort((a, b) => b - a);
            }
        }

        // 如果数组为空,表示没有银饰剩余,输出 0
        if (silverPieces.length === 0) {
            console.log(0);
        } else {
            // 否则输出剩余银饰的重量(数组中的最大值)
            console.log(silverPieces[0]);
        }
        // 关闭 readline 接口
        rl.close();
    }
});

23.内存冷热标记

// 引入 readline 模块用于读取命令行输入
const readline = require('readline');

// 创建 readline 接口实例
const rl = readline.createInterface({
  input: process.stdin, // 标准输入流
  output: process.stdout // 标准输出流
});

// 用于存储输入行的数组
let inputLines = [];

// 监听 'line' 事件,每次输入后触发
rl.on('line', (line) => {
  // 将输入的每一行添加到 inputLines 数组
  inputLines.push(line);
  // 当输入行数达到 3 行时,关闭 readline 接口
  if (inputLines.length === 3) {
    rl.close();
  }
}).on('close', () => {
  // 解析输入的第一行为页面访问次数
  const pageAccessCount = parseInt(inputLines[0].trim(), 10);
  // 解析输入的第二行为页面访问序列,转换为数字数组
  const pageAccessSequence = inputLines[1].trim().split(' ').map(Number);
  // 解析输入的第三行为热门页面的阈值
  const hotThreshold = parseInt(inputLines[2].trim(), 10);

  // 使用 reduce 方法统计每个页面的访问频率
  const pageFrequency = pageAccessSequence.reduce((acc, page) => {
    acc[page] = (acc[page] || 0) + 1; // 如果页面已存在则增加计数,否则初始化为 1
    return acc;
  }, {});

  // 根据阈值过滤出热门页面,并转换为数字数组
  const hotPages = Object.entries(pageFrequency)
    .filter(([page, freq]) => freq >= hotThreshold)
    .map(([page]) => parseInt(page, 10));

  // 输出热门页面的数量
  console.log(hotPages.length);

  // 如果存在热门页面
  if (hotPages.length > 0) {
    // 对热门页面进行排序,先按访问频率降序,频率相同则按页面号升序
    hotPages.sort((a, b) => {
      return pageFrequency[b] - pageFrequency[a] || a - b;
    });

    // 输出排序后的热门页面
    hotPages.forEach((page) => {
      console.log(page);
    });
  }

 
});

24.学生排名(排序比较)

/*
 * @Author: liwen liwen01@raxtone.com
 * @Date: 2024-04-03 14:21:09
 * @LastEditors: liwen liwen01@raxtone.com
 * @LastEditTime: 2024-04-03 14:21:13
 * @FilePath: \raxtone\Javasctipt\xuesehngpaiwming.js
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
// 引入 readline 模块用于读取命令行输入
const readline = require('readline');

// 创建 readline 接口实例
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

// 定义学生类
class Student {
  constructor(name) {
    this.name = name; // 学生姓名
    this.totalScore = 0; // 学生总分
    this.scores = {}; // 存储学生各科成绩的映射
  }

  // 添加成绩的方法,同时累加到总分
  addScore(subject, score) {
    this.scores[subject] = score;
    this.totalScore += score;
  }

  // 获取指定科目的成绩,若没有则返回0
  getScore(subject) {
    return this.scores[subject] || 0;
  }
}

// 创建一个异步处理函数
async function processInput() {
  // 通过 readline 逐行读取输入
  const lines = [];
  for await (const line of rl) {
    lines.push(line);
  }

  // 解析输入数据
  const [n, m] = lines[0].split(' ').map(Number);
  const subjects = lines[1].split(' ');
  const students = [];

  // 读取每个学生的姓名和成绩
  for (let i = 0; i < n; i++) {
    const tokens = lines[i + 2].split(' ');
    const student = new Student(tokens[0]);
    for (let j = 0; j < m; j++) {
      student.addScore(subjects[j], parseInt(tokens[j + 1], 10));
    }
    students.push(student);
  }

  // 读取用作排名的科目名称
  const rankSubject = lines[n + 2];

  // 对学生列表进行排序
  students.sort((s1, s2) => {
    const score1 = rankSubject === '' ? s1.totalScore : s1.getScore(rankSubject);
    const score2 = rankSubject === '' ? s2.totalScore : s2.getScore(rankSubject);
    if (score1 !== score2) {
      return score2 - score1; // 降序排序
    } else {
      return s1.name.localeCompare(s2.name); // 成绩相同则按姓名升序排序
    }
  });

  // 输出排序后的学生姓名
  students.forEach(student => process.stdout.write(`${student.name} `));
  process.stdout.write('\n');

  // 关闭 readline 接口
  rl.close();
}

// 调用异步处理函数
processInput();

25.小明找位置(二分法)

const readline = require('readline');

// 创建 readline 接口实例
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});


rl.on('line', (line) => {
    // 读取小明的学号
    rl.on('line', (xiaoMingNumber) => {
        xiaoMingNumber = parseInt(xiaoMingNumber);

        // 分割字符串并转换为整数数组
        const numbers = line.split(',').map(num => parseInt(num.trim()));

        // 对数组进行排序
        numbers.sort((a, b) => a - b);

        // 使用二分查找算法找到小明的位置
        let left = 0, right = numbers.length, mid;
        while (left < right) {
            mid = Math.floor((left + right) / 2);
            if (numbers[mid] < xiaoMingNumber) {
                left = mid + 1;
            } else {
                right = mid;
            }
        }
        const position = left;

        // 输出小明应该排的位置,位置从1开始计数
        console.log(position + 1);
        process.exit();
    });
});

 26.执行任务赚获取最多积分(贪心)

const readline = require('readline');

// 创建readline接口实例
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

// 创建一个小根堆类
class MinHeap {
    constructor() {
        this.heap = [];
    }

    // 获取父节点的索引
    getParentIndex(i) {
        return Math.floor((i - 1) / 2);
    }

    // 获取左子节点的索引
    getLeftChildIndex(i) {
        return 2 * i + 1;
    }

    // 获取右子节点的索引
    getRightChildIndex(i) {
        return 2 * i + 2;
    }

    // 交换堆中两个元素的位置
    swap(i, j) {
        [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
    }

    // 向堆中插入一个元素
    push(key) {
        this.heap.push(key);
        this.heapifyUp();
    }

    // 移除并返回堆顶元素(最小值)
    pop() {
        if (this.size() === 1) {
            return this.heap.pop();
        }

        const top = this.heap[0];
        this.heap[0] = this.heap.pop();
        this.heapifyDown();
        return top;
    }

    // 返回堆顶元素(最小值)
    peek() {
        return this.heap[0];
    }

    // 返回堆的大小
    size() {
        return this.heap.length;
    }

    // 向上调整堆
    heapifyUp() {
        let index = this.heap.length - 1;
        while (this.getParentIndex(index) >= 0 && this.heap[this.getParentIndex(index)] > this.heap[index]) {
            this.swap(this.getParentIndex(index), index);
            index = this.getParentIndex(index);
        }
    }

    // 向下调整堆
    heapifyDown() {
        let index = 0;
        while (this.getLeftChildIndex(index) < this.size()) {
            let smallerChildIndex = this.getLeftChildIndex(index);
            if (this.getRightChildIndex(index) < this.size() && this.heap[this.getRightChildIndex(index)] < this.heap[smallerChildIndex]) {
                smallerChildIndex = this.getRightChildIndex(index);
            }

            if (this.heap[index] < this.heap[smallerChildIndex]) {
                break;
            } else {
                this.swap(index, smallerChildIndex);
            }

            index = smallerChildIndex;
        }
    }
}


let lineCount = 0;
let n, T;
let tasks = [];
let totalScore = 0;

rl.on('line', (line) => {
    if (lineCount === 0) {
        n = parseInt(line);
    } else if (lineCount === 1) {
        T = parseInt(line);
    } else {
        const [deadline, score] = line.split(' ').map(Number);
        tasks.push({ deadline, score });
        if (tasks.length === n) {
            rl.close();
        }
    }
    lineCount++;
});

rl.on('close', () => {
    tasks.sort((a, b) => a.deadline - b.deadline);
    const minHeap = new MinHeap();
    tasks.forEach(task => {
        const { deadline, score } = task;
        if (minHeap.size() < deadline) {
            minHeap.push(score);
        } else if (minHeap.size() > 0 && minHeap.peek() < score) {
            minHeap.pop();
            minHeap.push(score);
        }
        if (minHeap.size() > T) {
            minHeap.pop();
        }
    });

    while (minHeap.size() > 0) {
        totalScore += minHeap.pop();
    }

    console.log(totalScore);
});

27.购买最多宝石(滑动窗口)

const readline = require('readline').createInterface({
    input: process.stdin,
    output: process.stdout
});

let input = [];

readline.on('line', (line) => {
    input.push(line);
});

readline.on('close', () => {
    // 读取宝石的数量
    const n = parseInt(input[0]);
    // 创建一个数组来存储每个宝石的价格
    const gems = input.slice(1, n + 1).map(Number);
    // 读取你拥有的钱的总面值
    const value = parseInt(input[n + 1]);

    // 初始化滑动窗口的左右边界和窗口内宝石的总价
    let left = 0, right = 0, sum = 0;
    // 初始化最大可购买的宝石数量
    let maxT = 0;
    // 当滑动窗口的右边界没有超过宝石数量时,继续循环
    while (right < gems.length) {
        // 将右边界的宝石价格加到总价中
        sum += gems[right];
        // 当总价超过你拥有的钱时,将左边界的宝石价格从总价中减去,并将左边界向右移动
        while (sum > value) {
            sum -= gems[left];
            left++;
        }
        // 更新最大可购买的宝石数量
        maxT = Math.max(maxT, right - left + 1);
        // 将右边界向右移动
        right++;
    }
    // 输出最大可购买的宝石数量
    console.log(maxT);
});

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值