leetcode 1298. 你能从盒子里获得的最大糖果数(javascript)

给你 n 个盒子,每个盒子的格式为 [status, candies, keys, containedBoxes] ,其中:

  • 状态字 status[i]:整数,如果 box[i] 是开的,那么是 1 ,否则是 0 。 糖果数 candies[i]: 整数,表示
    box[i] 中糖果的数目。
  • 钥匙 keys[i]:数组,表示你打开 box[i] 后,可以得到一些盒子的钥匙,每个元素分别为该钥匙对应盒子的下标。
  • 内含的盒子 containedBoxes[i]:整数,表示放在 box[i] 里的盒子所对应的下标。
  • 给你一个 initialBoxes
    数组,表示你现在得到的盒子,你可以获得里面的糖果,也可以用盒子里的钥匙打开新的盒子,还可以继续探索从这个盒子里找到的其他盒子。

请你按照上述规则,返回可以获得糖果的 最大数目 。

初看此题,就打算用bfs解。这道既然属于困难题,那么肯定不能用常规bfs方法套。首先看开盒条件:

  • 盒子序号在initialBoxes数组中(手中有这个盒子)
  • 盒子序号在keys数组中(手中有盒子的钥匙)

那么可以先尝试写出来bfs的模板:

var maxCandies = function(status, candies, keys, containedBoxes, initialBoxes) {
    var ans=0;
    while(initialBoxes.length){
        let temp=initialBoxes.shift();
        if(status[temp]==1){
            ans+=candies[temp];
            for(let i=0;i<keys[temp].length;i++){
                status[keys[temp][i]]=1;
            }
            for(let i=0;i<containedBoxes[temp].length;i++){
                initialBoxes.push(containedBoxes[temp][i]);
            }
        }
    }
    return ans;
};

写出来模板问题就清晰多了。我发现这道题的关键在于,遍历时可能当前拥有的盒子刚好此刻没有钥匙。但这并不代表此后不会从其他盒子中开出当前盒子的钥匙,如果只是让当前拥有的盒子简单出队,那么必然会少开很多盒子。
那么很简单,当当前没有钥匙时,我们不要让他出队。

else{
    initialBoxes.push(temp);
}

成功解决可能会错过钥匙的问题后,新的问题来了。当题目所给的数据可能无法开完所有盒子时,这段代码将进入死循环。

那么我们需要找到一个跳出循环的办法。我一开始认为,当死循环时,剩余没拿到的钥匙数等于当前拥有盒子数,那么我就用这个条件。然后我就发现这只是死循环的必要不充分条件。

那么怎么样才会算进入死循环呢?其实,只要钥匙集合与拥有盒子的集合没有交集,那么就肯定无法继续开盒子了。那么,最终代码就来了。

var maxCandies = function(status, candies, keys, containedBoxes, initialBoxes) {
    var ans=0;
    while(initialBoxes.length){
        let flag=initialBoxes.some(function(item,index,arr){
            return status[item]==1;
        })
        if(!flag)   return ans;
        let temp=initialBoxes.shift();
        if(status[temp]==1){
            ans+=candies[temp];
            for(let i=0;i<keys[temp].length;i++){
                status[keys[temp][i]]=1;
            }
            for(let i=0;i<containedBoxes[temp].length;i++){
                initialBoxes.push(containedBoxes[temp][i]);
            }
        }
        else{
            initialBoxes.push(temp);
        }
    }
    return ans;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值