leetcode-pp / 91alg-13-daily-check

0 stars 0 forks source link

【Day 52 】2024-05-29 - 1298. 你能从盒子里获得的最大糖果数 #53

Open azl397985856 opened 1 month ago

azl397985856 commented 1 month ago

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

入选理由

暂无

题目地址

https://leetcode.cn/problems/maximum-candies-you-can-get-from-boxes/

前置知识

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

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

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

 

示例 1:

输入:status = [1,0,1,0], candies = [7,5,4,100], keys = [[],[],[1],[]], containedBoxes = [[1,2],[3],[],[]], initialBoxes = [0] 输出:16 解释: 一开始你有盒子 0 。你将获得它里面的 7 个糖果和盒子 1 和 2。 盒子 1 目前状态是关闭的,而且你还没有对应它的钥匙。所以你将会打开盒子 2 ,并得到里面的 4 个糖果和盒子 1 的钥匙。 在盒子 1 中,你会获得 5 个糖果和盒子 3 ,但是你没法获得盒子 3 的钥匙所以盒子 3 会保持关闭状态。 你总共可以获得的糖果数目 = 7 + 4 + 5 = 16 个。 示例 2:

输入:status = [1,0,0,0,0,0], candies = [1,1,1,1,1,1], keys = [[1,2,3,4,5],[],[],[],[],[]], containedBoxes = [[1,2,3,4,5],[],[],[],[],[]], initialBoxes = [0] 输出:6 解释: 你一开始拥有盒子 0 。打开它你可以找到盒子 1,2,3,4,5 和它们对应的钥匙。 打开这些盒子,你将获得所有盒子的糖果,所以总糖果数为 6 个。 示例 3:

输入:status = [1,1,1], candies = [100,1,100], keys = [[],[0,2],[]], containedBoxes = [[],[],[]], initialBoxes = [1] 输出:1 示例 4:

输入:status = [1], candies = [100], keys = [[]], containedBoxes = [[]], initialBoxes = [] 输出:0 示例 5:

输入:status = [1,1,1], candies = [2,3,2], keys = [[],[],[]], containedBoxes = [[],[],[]], initialBoxes = [2,1,0] 输出:7  

提示:

1 <= status.length <= 1000 status.length == candies.length == keys.length == containedBoxes.length == n status[i] 要么是 0 要么是 1 。 1 <= candies[i] <= 1000 0 <= keys[i].length <= status.length 0 <= keys[i][j] < status.length keys[i] 中的值都是互不相同的。 0 <= containedBoxes[i].length <= status.length 0 <= containedBoxes[i][j] < status.length containedBoxes[i] 中的值都是互不相同的。 每个盒子最多被一个盒子包含。 0 <= initialBoxes.length <= status.length 0 <= initialBoxes[i] < status.length

Lizhao-Liu commented 1 month ago
class Solution {
    private var status = [Int]()
    func maxCandies(_ status: [Int], _ candies: [Int], _ keys: [[Int]], _ containedBoxes: [[Int]], _ initialBoxes: [Int]) -> Int {
        self.status = status
        var totalCandies = 0
        var myKeys: Set<Int> = []
        var unOpenedBoxes: Set<Int> = []
        var boxQueue = initialBoxes

        while !boxQueue.isEmpty {
            let box = boxQueue.removeFirst()

            if self.status[box] == 1 { // box is open
                totalCandies += candies[box]

                for key in keys[box] {
                    if unOpenedBoxes.contains(key) {
                        unOpenedBoxes.remove(key)
                        self.status[key] = 1
                        boxQueue.append(key)
                    } else {
                        myKeys.insert(key)
                    }
                }

                for containedBox in containedBoxes[box] {
                    boxQueue.append(containedBox)
                }

            } else {
                if myKeys.contains(box) {
                    self.status[box] = 1
                    boxQueue.append(box)
                } else {
                    unOpenedBoxes.insert(box)
                }
            }
        }

        return totalCandies
    }
}
CathyShang commented 1 month ago

题目虽然是最大,但事实是将能够开的盒子都开了求从中获取糖果数。 那么需要一层一层开,开盒子的条件:

  1. 获得了,本身盒子是开的
  2. 获得了,本身是关着的,又获得了钥匙
class Solution {
public:
    int maxCandies(vector<int>& status, vector<int>& candies, vector<vector<int>>& keys, vector<vector<int>>& containedBoxes, vector<int>& initialBoxes) {
      int ans=0;
      unordered_map<int, pair<int,int>> hash; // 盒子索引(是否获取,是否有钥匙)
      queue<int> q; // 可获取盒子索引
      // 查看初始化 initialBoxes
      if(initialBoxes.empty()) return ans;
      else{
        for(auto init:initialBoxes){
          q.push(init);
        }
      }
      // 维护队列
      while(!q.empty()){
        int cur = q.front();
        // 判断是否能开启
        if(status[cur]==1){
          ans += candies[cur];
          // 看看有没有钥匙
          if(!keys[cur].empty()){
            for(auto key:keys[cur]){
              status[key] = 1; // 有钥匙设置状态为1
              auto it = hash.find(key);
              if( it!=hash.end() ){
                q.push(key);
                hash.erase(key); // 删除               
              }
            }
          }
          // 放入获得的盒子
          for(auto box:containedBoxes[cur]){
            q.push(box);
          }
        }
        else{
          hash[cur] = {1,0}; // 存一些没有钥匙的盒子
        }

        q.pop();//删除

      }
      return ans;
    }
};

时间复杂度: $O(n)$

空间复杂度: $O(n)$

Dtjk commented 1 month ago
public int findShortestCircleContainingTarget(List<List<Integer>> graph, int target) {
        Queue<Integer> queue = new ArrayDeque<>();
        Set<Integer> seen = new HashSet<>();
        queue.offer(target);

        int len = 0;
        while (!queue.isEmpty()) {
            len++;
            for (int size = queue.size(); size > 0; size--) {
                var cur = queue.poll();
                seen.add(cur);

                for (var next : graph.get(cur)) {
                    if (!seen.contains(next))
                        queue.offer(next);
                    else if (next == target)
                        return len;
                }
            }
        }

        return -1;
    }
hillsonziqiu commented 1 month ago

原理

代码

/**
 * @param {number[]} status
 * @param {number[]} candies
 * @param {number[][]} keys
 * @param {number[][]} containedBoxes
 * @param {number[]} initialBoxes
 * @return {number}
 */
var maxCandies = function(status, candies, keys, containedBoxes, initialBoxes) {
    const needKeys = new Set();
    let sum = 0;
    let queue = initialBoxes;
    while (queue.length) {
        const i = queue.shift();
        if (status[i]) {
            sum += candies[i];
            queue.push(...containedBoxes[i]);
            for (const key of keys[i]) {
                status[key] = 1;
                if (needKeys.has(key)) {
                    queue.push(key);
                    needKeys.delete(key);
                }
            }
        } else {
            needKeys.add(i)
        }
    }

    return sum;
};

复杂度分析

zhiyuanpeng commented 1 month ago

def maxCandies(self, status, candies, keys, containedBoxes, initialBoxes): boxes = set(initialBoxes) q = [i for i in boxes if status[i]] for i in q: for j in containedBoxes[i]: boxes.add(j) if status[j]: q.append(j) for j in keys[i]: if status[j] == 0 and j in boxes: q.append(j) status[j] = 1 return sum(candies[i] for i in q)