微软8.13笔试 前端JS编程题*3

我觉得这次比上次简单一点🤣

- 微软的笔试不分啥前后端的,题目都一样,这里主要说明用JS做的题解;(多余说一句,从题干上来说,微软的题和现实生活联系得最紧密)

- 题目有老哥贴出来了https://www.nowcoder.com/discuss/1013487


编程题

1. 防治污染


  1. 纯暴力解法,每次把最大值过滤下就行了,但是我处理得是每次用Math.max(...arr)去找最大值;
  2. 有人说用最大堆,但是JS没有可用的API呀,得自己手写,这样会来不及吧
function solution(A) {
  // 累计求需要减少的排放量
  let pollution = A.reduce((sum, cur) => cur + sum),
    target = pollution / 2;
  let count = 0;
  while (target > 0) {
    // 每次把污染最大的厂找到并filter
    let maxPollution = Math.max(...A);
    let index = A.indexOf(maxPollution);
    count++;
    target -= A[index] / 2;
    if (target <= 0) {
      return count;
    }
    // 原厂的污染减半,并修改值。因为有可能你减半以后还是很大,下次还会来filter你
    A[index] = A[index] / 2;
  }
  return count;
}
console.log(solution([7, 19, 8, 2]));
2. 小数对和为1


  1. 我觉得分子、分母有些难处理,而且分数还涉及到通分,尤其是JS的小数又涉及到精确度的问题,所以我就先求出了分母的最小公倍数,再将分数通分,最后就演变成了`在分子数组找两个数的和为最小公倍数`,这不就是两数之和的问题嘛!!
  2. 但是最小公倍数值会不会太大,超过数据范围就不得而知了
  3. 但是我审题不清,没注意a pair of,还想着会不会有2项、3项……之和的情况
function solution(X, Y) {
  let minMom = getMinMom(Y);
  let newX = X.map((val, index) => (val * minMom) / Y[index]).sort();
  // 往下就是求两数之和了——————力扣第一题,呜心痛
  let map = new Map(),
    res = 0;
  for (let item of newX) {
    // 这个一半的情况留着单独讨论
    if (item === minMom / 2) {
      map.set(item, (map.get(item) || 0) + 1);
    } else {
      map.set(item, (map.get(item) || 0) + 1);
      if (map.has(minMom - item)) {
        res += map.get(minMom - item);
      }
    }
  }
  if (map.has(minMom / 2) && map.get(minMom / 2) > 1) {
    // 这里要算组合
    let count = map.get(minMom / 2);
    res += (count * (count - 1)) / 2;
  }
  return res;
}
console.log(solution([1, 1, 2], [3, 2, 3])); // 1

// 取公倍数
function getMinMom(Y) {
  let res = 1;
  Y.forEach((i) => {
    if (res % i !== 0) {
      if (i % res === 0) {
        res = i;
      } else {
        res *= i;
      }
    }
  });
  return res;
}
3. 坚持治疗

  1. 当时就一个疑惑,比如做一次治疗要间隔Y天后再做第二次,但是Y天后一定要立刻去做嘛?还是说可能找一个更便宜的时候去呢?最后看例子以及题干的描述,觉得就是`间隔Y天后一定要接着做第二次` 
  2. 然后就是暴力遍历求解了
  3. 我看有人提到`前缀和`,可以参考力扣303题。确实这个可以少一点运算啦,但是这个每次治疗间隔Y天,不是一天哦,所以麻烦一点。
// 暴力解法
function solution(A, X, Y) {
  // dayCost做完治疗要花的天数;totalCost要花的钱,这样就可以遍历比较了。
  let dayCost = Y * (X - 1) + 1,
    totalCost = Number.MAX_VALUE;
  for (let i = 0; i <= A.length - dayCost; i++) {
    let count = X,
      j = i,
      cost = 0;
    while (count > 0) {
      cost += A[j];
      j += Y;
      count--;
    }
    totalCost = Math.min(totalCost, cost);
  }
  return totalCost;
}

console.log(solution([4, 2, 3, 7], 2, 2));

// 使用了前缀和
function solution(A, X, Y) {
  // dayCost做完治疗要花的天数;totalCost要花的钱;deadline是最迟这天要开始治疗,不然就来不及了
  let dayCost = Y * (X - 1) + 1,
    totalCost = Number.MAX_VALUE,
    deadline = A.length - dayCost;
  // Y 是控制了一个循环,每轮循环中的不同治疗方案才有重复的日期,才能用前缀和。
  for (let i = 0; i < Y && i <= deadline; i++) {
    // j是本轮治疗起始的日子
    let cost = 0;
    for (let j = i; j <= deadline; j += Y) {
      if (j !== i) {
        // 前缀和就这点好处啦,有的情况下就不用循环计算了
        cost = cost - A[j - Y] + A[j - Y * (X - 1)];
      } else {
        let count = X,
          index = j;
        while (count > 0) {
          cost += A[index];
          index += Y;
          count--;
        }
      }
      totalCost = Math.min(totalCost, cost);
    }
  }

  return totalCost;
}

console.log(solution([10, 3, 4, 7], 2, 3));  // 17

#微软##微软笔试#
全部评论
2.3都可以更简单的,微软的话挺注重最优解的
点赞 回复 分享
发布于 2022-08-14 06:14
微软需要英文简历吗
点赞 回复 分享
发布于 2022-08-14 00:48

相关推荐

评论
1
17
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务