力扣上的一个中等难度的题,之所以写一篇博客记录下来,是因为貌似触发了力扣的彩蛋,第一次遇见,感觉挺有意义的。
题目如下:
一个 ATM 机器,存有 5 种面值的钞票:20 ,50 ,100 ,200 和 500 美元。初始时,ATM 机是空的。用户可以用它存或者取任意数目的钱。
取款时,机器会优先取 较大 数额的钱。
比方说,你想取 $300 ,并且机器里有 2 张 $50 的钞票,1 张 $100 的钞票和1 张 $200 的钞票,那么机器会取出 $100 和 $200 的钞票。
但是,如果你想取 $600 ,机器里有 3 张 $200 的钞票和1 张 $500 的钞票,那么取款请求会被拒绝,因为机器会先取出 $500 的钞票,然后无法取出剩余的 $100 。注意,因为有 $500 钞票的存在,机器 不能 取 $200 的钞票。请你实现 ATM 类:
ATM() 初始化 ATM 对象。
void deposit(int[] banknotesCount) 分别存入 $20 ,$50,$100,$200 和 $500 钞票的数目。
int[] withdraw(int amount) 返回一个长度为 5 的数组,分别表示 $20 ,$50,$100 ,$200 和 $500 钞票的数目,并且更新 ATM 机里取款后钞票的剩余数量。如果无法取出指定数额的钱,请返回 [-1] (这种情况下不取出任何钞票)。
题目解析
这道题的意思是,ATM机中原有的钞票数都为0,直到我们往里面存钱之后,才会有钱。但是当我们取钱的时候,只要有大数值面额的钞票,并且我所要取的钱比这个数值面额要大,那就会先取这个数额的钞票。
举个例子:我要取600块,因为机器中存在500块的钞票,因此我不能去取200块的,只能取500块的,之后还剩下100块要取的额度,虽然存在200块,但是我现在要取的比200小,因此向下找,直接取100块的,至此完成操作。
代码解析
var ATM = function() {
this.moneys = [0,0,0,0,0];
this.size = [20,50,100,200,500];
};
/**
* @param {number[]} banknotesCount
* @return {void}
*/
ATM.prototype.deposit = function(banknotesCount) {
for(let i=0;i<5;i++){
this.moneys[i]+=banknotesCount[i];
}
};
/**
* @param {number} amount
* @return {number[]}
*/
ATM.prototype.withdraw = function(amount) {
let give = [0,0,0,0,0];
let temp = [...this.moneys];
let pieces,last=0;
for(let i=4;i>=0;i--){
pieces = Math.floor(amount/this.size[i]);
last = amount%this.size[i];
if(pieces>=this.moneys[i]){
give[i] += this.moneys[i];
last += this.size[i]*(pieces-this.moneys[i]);
this.moneys[i] = 0
}else{
this.moneys[i] -= pieces;
give[i] += pieces;
}
amount = last;
}
if(amount!==0){
this.moneys = temp;
return [-1]
};
return give;
};
原数组
为了代表钞票额度和每种额度钞票的数量,我在原函数中设置了两个数组,moneys数组用于代表每种额度钞票的数量,size数组用于代码这种钞票额度的大小。
deposit方法实现
deposit方法很容易实现,只需要一个for循环,遍历输入的数组,将新增对应额度的钞票数量加到moneys数组中对应的位置即可。
withdraw方法实现
withdraw方法,也就是取钱的方法,是这道题的核心。要求我们若是ATM机中的钞票数量足以满足取钱要求的话,就返回一个数组,数组代表要取出的每种钞票的数量。否则返回[-1]。
因此我设置了一个全零数组give,代表要取出的钞票数组,还用一个数组对moneys进行了深复制,供我们在不满足取钱要求的时候,可以将moneys恢复原形。为了更好的计算对每种钞票数量的要求,我设置了两个变量pieces、last,代表对当前钞票数量的需求和剩下要取钱的额度。
之后就开始for循环遍历了,先用要取的钱除以当前面值,代表尽可能取当前面值的钞票,要是当前面值的钞票数量不足以供应时,则将剩下那部分加上之前取余的数值,成为接下来要取的额度。
运行结果
应该是这道题比较冷门,写的人比较少,并且这一刻我电脑慢了许久的网速突然间快了起来,最后刷新了这道题js算法的执行用时,值得纪念一下。