第一题、赢得比赛需要的最少训练时长
题目:
你正在参加一场比赛,给你两个 正 整数
initialEnergy
和initialExperience
分别表示你的初始精力和初始经验。
另给你两个下标从 0 开始的整数数组energy
和experience
,长度均为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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。