LeetCode 第 307 场周赛 复盘

第一题、赢得比赛需要的最少训练时长

题目:

你正在参加一场比赛,给你两个 整数 initialEnergyinitialExperience 分别表示你的初始精力和初始经验。
另给你两个下标从 0 开始的整数数组 energyexperience,长度均为 n
你将会 依次 对上 n 个对手。第 i 个对手的精力和经验分别用 energy[i]experience[i] 表示。当你对上对手时,需要在经验和精力上都 严格 超过对手才能击败他们,然后在可能的情况下继续对上下一个对手。
击败第 i 个对手会使你的经验 增加 experience[i],但会将你的精力 减少 energy[i]
在开始比赛前,你可以训练几个小时。每训练一个小时,你可以选择将增加经验增加 1 或者 将精力增加 1 。

返回击败全部 n 个对手需要训练的 最少 小时数目。

示例:

输入:initialEnergy = 5, initialExperience = 3, energy = [1,4,3,2], experience = [2,6,3,1]
输出:8
解释:在 6 小时训练后,你可以将精力提高到 11 ,并且再训练 2 个小时将经验提高到 5 。
按以下顺序与对手比赛:

  • 你的精力与经验都超过第 0 个对手,所以获胜。
    精力变为:11 - 1 = 10 ,经验变为:5 + 2 = 7 。
  • 你的精力与经验都超过第 1 个对手,所以获胜。
    精力变为:10 - 4 = 6 ,经验变为:7 + 6 = 13 。
  • 你的精力与经验都超过第 2 个对手,所以获胜。
    精力变为:6 - 3 = 3 ,经验变为:13 + 3 = 16 。
  • 你的精力与经验都超过第 3 个对手,所以获胜。
    精力变为:3 - 2 = 1 ,经验变为:16 + 1 = 17 。
    在比赛前进行了 8 小时训练,所以返回 8 。
    可以证明不存在更小的答案。

输入:initialEnergy = 2, initialExperience = 4, energy = [1], experience = [3]
输出:0
解释:你不需要额外的精力和经验就可以赢得比赛,所以返回 0 。

这一题很简单,只需要初始精力大于精力总和即可(大1),然后就是遍历 experience 保证初始经验在累加过程中始终大于该值即可 。
要求的是最少*小时数目,所以只需要大于1即可。
下面是代码:

var minNumberOfHours = function(initialEnergy, initialExperience, energy, experience) {
    let needEnergy = 0, needExper = 0;
    needEnergy = energy.reduce((pre, cur) => pre+cur, 1)- initialEnergy;
    
    for(let i = 0;i<experience.length;i++) {
        if(initialExperience <= experience[i]) {
            needExper += experience[i] - initialExperience + 1;
            initialExperience += needExper;
        }
        initialExperience += experience[i];
    }
    return needExper + needEnergy;
};

但是,提交之后会有一个示例过不去😅,而且不给显示那个具体的案例😅。

为保障竞赛的公平性,力扣将在竞赛中隐藏部分用例。当参赛者在竞赛中提交未通过时,力扣不会显示给参赛者被隐藏的错误用例。

痛,太痛了。找了半天才发现是我的所需精力的算法有问题,needEnergy = energy.reduce((pre, cur) => pre+cur, 1)- initialEnergy; 这句,初始精力有可能大于energy的总和,所以可能会出现负值,但是根据题意,需要将其变为 0。
最终代码:

/**
 * @param {number} initialEnergy
 * @param {number} initialExperience
 * @param {number[]} energy
 * @param {number[]} experience
 * @return {number}
 */
var minNumberOfHours = function(initialEnergy, initialExperience, energy, experience) {

    let needEnergy = 0, needExper = 0;
    needEnergy = energy.reduce((pre, cur) => pre+cur, 1)- initialEnergy;
    if(needEnergy < 0) {
        needEnergy = 0;
    }
    
    for(let i = 0;i<experience.length;i++) {
        if(initialExperience <= experience[i]) {
            needExper += experience[i] - initialExperience + 1;
            initialExperience += needExper;
        }
        initialExperience += experience[i];
    }
    return needExper + needEnergy;
};

第二题、最大回文数字

给你一个仅由数字(0 - 9)组成的字符串 num 。
请你找出能够使用 num 中数字形成的 最大回文 整数,并以字符串形式返回。该整数不含 前导零 。
注意:

  • 你 无需 使用 num 中的所有数字,但你必须使用 至少 一个数字。
  • 数字可以重新排序。

示例1:
输入:num = “444947137”
输出:“7449447”
解释:
从 “444947137” 中选用数字 “4449477”,可以形成回文整数 “7449447” 。
可以证明 “7449447” 是能够形成的最大回文整数。

示例 2:
输入:num = “00009”
输出:“9”
解释:
可以证明 “9” 能够形成的最大回文整数。
注意返回的整数不应含前导零。

这一题我也调试了半天才过😅

解题思路:

  • 首先创建一个长为10(0~9)的数组用于保存对应数字(下标)的个数。然后遍历num将对应数字的个数存入数组map
  • 题目要求的是最大回文整数,所以从大到小遍历数组map,如果有个数字的数量大于等于2,即可放入结果数组ans中,然后将其去掉2个。
  • 由于要求 不应含前导零 ,所以当结果数组ans中无数字且遍历到0时,应掠过0
  • 接着需要找到一个中间数,即找到遍历后的数组中的最大值加入进去。
  • 最后将结果数组ans复制一份,反转加到ans尾部;拼接起来就是结果。

然后就是经典差一个示例不过😅,排查起来才发现是回文中间不一定会有单个数,也有可能没有,所以要加个变量判断是否要加(数组是否还剩数)。

/**
 * @param {string} num
 * @return {string}
 */
var largestPalindromic = function (num) {
  let map = new Array(10).fill(0);
  for (let i = 0; i < num.length; i++) {
    map[num[i]]++;
  }
  let ans = [], isInsert = true;
  for (let i = 9; i >= 0; i--) {
    if (ans.length === 0 && i == 0) {
      continue;
    }
    while (map[i] >= 2) {
      ans.push(i);
      map[i] -= 2;
    }
  }
  for (let i = 9; i >= 0; i--) {
    if(map[i] === 0) {
      isInsert = false;
    } else {
      isInsert = true;
      ans.push(i);
      break;
    }
  }
  const a = ans.slice().reverse();
  if( isInsert) {
    ans.push(...a.slice(1));
  } else {
    ans.push(...a.slice());
  }
  return ans.join("");
};

后两题

什么,你问后两题咋没有?那我只能说本人菜鸟一个,只能做出前两题😅😅😅

经过不懈的努力(摆烂),本人已经是力扣周赛基本稳定2题的选手,正在冲击第三题。

下面给出后两题链接,希望有大佬给讲解一下🤣

来源:力扣(LeetCode)
链接:https://leetcode.cn
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值