iT邦幫忙

2026 iThome 鐵人賽

DAY 23
0
Software Development

30天刷完leetcoode75系列 第 23 篇

C++ 演算法練習 Day23|994, 2462, 1318 題解與思路分享

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20261007/20184265Sm2hcQWc9c.png

題目解析:網格中包含新鮮與腐爛的橘子,腐爛橘子每分鐘會傳染給上下左右相鄰的新鮮橘子。求全部橘子都腐爛所需的最短時間,若有橘子無法被傳染到則回傳 -1
解題思路:找出所有腐爛橘子當作起點,將初始時間設為 2 並丟進 DFS 遞迴。若遇到邊界、空位或是有更早腐爛的紀錄就直接中斷。遞迴結束後全圖掃描找最大時間,若發現有新鮮橘子殘留就回傳 -1,否則將最大時間減 2 即為花費的總分鐘數

class Solution {
public:
    int orangesRotting(vector<vector<int>>& grid) {
        int m = grid.size(), n = grid[0].size();

        for (int y = 0; y < m; y++)
            for (int x = 0; x < n; x++)
                if (grid[y][x] == 2) solve(grid, y, x, 2);

        int ans = 2;
        for (auto& it : grid)
            for (int v : it) {
                if (v == 1) return -1;
                ans = max(ans, v);
            }
        return ans - 2;
    }

    void solve(vector<vector<int>>& grid, int y, int x, int time) {
        if (y < 0 || x < 0 || y >= grid.size() || x >= grid[0].size()) return;
        if (grid[y][x] == 0) return;
        if (grid[y][x] > 1 && grid[y][x] < time) return;

        grid[y][x] = time;
        solve(grid, y + 1, x, time + 1);
        solve(grid, y - 1, x, time + 1);
        solve(grid, y, x + 1, time + 1);
        solve(grid, y, x - 1, time + 1);
    }
};

https://ithelp.ithome.com.tw/upload/images/20261007/2018426574IBMiPLQS.png

題目解析:需要雇用 k 個工人,每次只能從名單最前面或最後面各 candidates 個工人之中,挑選成本最低的人,若成本同分則優先挑選索引在前面的,求總雇用花費
解題思路:設兩個由小到大排的優先佇列裝頭尾候選人,並以雙指標記錄目前進度。先將頭尾指定數量的工人塞入佇列,接著丟進迴圈跑 k 次。每次比較兩邊佇列的最小成本,把較便宜的那方加入總和並從佇列剔除,接著從同一側再補一個新人進去,最後回傳總花費

class Solution {
public:
    long long totalCost(vector<int>& costs, int k, int candidates) {
        priority_queue<int, vector<int>, greater<int>> v, v1;
        int i = 0, j = costs.size()-1;

        for(int it = 0; it < candidates; it++){
            if(i <= j) v.push(costs[i++]);
            if(i <= j) v1.push(costs[j--]);
        }

        long long ans = 0;
        while(k--){
            if(v1.empty() || (!v.empty() && v.top() <= v1.top())){
                ans += v.top();
                v.pop();
                if(i <= j) v.push(costs[i++]);
            }else{
                ans += v1.top();
                v1.pop();
                if(i <= j) v1.push(costs[j--]);
            }
        }
        return ans;
    }
};

https://ithelp.ithome.com.tw/upload/images/20261007/2018426502uRKtUTyn.png

題目解析:給定 a、b、c 三個正整數,求最少需要翻轉 a 或 b 幾個二進位位元,才能讓 a OR b 的結果等於 c
解題思路:設變數 ans 記錄翻轉數。丟進迴圈每次比對三數最右側的位元,若 c 是 0,代表 a 和 b 該位元都必須是 0,兩者若皆為 1 就加 2 次翻轉;若 a OR b 目前位元已符合 c 就不需翻轉;其餘不合狀況皆只需加 1 次翻轉。比對完把數字除以 2 換下一個位元,直到三數歸零後回傳答案

class Solution {
public:
    int minFlips(int a, int b, int c) {
        int ans = 0;

        while (a != 0 || b != 0 || c != 0) {
            if (a % 2 == 1 && b % 2 == 1 && c % 2 == 0) {
                ans += 2;
            } else if ((a % 2 || b % 2) == c % 2) {
                ans += 0;
            } else {
                ans += 1;
            }

            a /= 2;
            b /= 2;
            c /= 2;
        }

        return ans;
    }
};

上一篇
C++ 演算法練習 Day22|162, 875 題解與思路分享
下一篇
C++ 演算法練習 Day24|1161, 236, 199 題解與思路分享
系列文
30天刷完leetcoode75 共 24 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言