[LeetCode] 1057. Campus Bikes 校園自行車



On a campus represented as a 2D grid, there are N workers and M bikes, with N <= M. Each worker and bike is a 2D coordinate on this grid.

Our goal is to assign a bike to each worker. Among the available bikes and workers, we choose the (worker, bike) pair with the shortest Manhattan distance between each other, and assign the bike to that worker. (If there are multiple (worker, bike) pairs with the same shortest Manhattan distance, we choose the pair with the smallest worker index; if there are multiple ways to do that, we choose the pair with the smallest bike index). We repeat this process until there are no available workers.

The Manhattan distance between two points p1 and p2 is Manhattan(p1, p2) = |p1.x - p2.x| + |p1.y - p2.y|.

Return a vector ans of length N, where ans[i] is the index (0-indexed) of the bike that the i-th worker is assigned to.

Example 1:

Input: workers = [[0,0],[2,1]], bikes = [[1,2],[3,3]]
Output: [1,0]
Explanation:
Worker 1 grabs Bike 0 as they are closest (without ties), and Worker 0 is assigned Bike 1. So the output is [1, 0].

Example 2:

Input: workers = [[0,0],[1,1],[2,0]], bikes = [[1,0],[2,2],[2,1]]
Output: [0,2,1]
Explanation:
Worker 0 grabs Bike 0 at first. Worker 1 and Worker 2 share the same distance to Bike 2, thus Worker 1 is assigned to Bike 2, and Worker 2 will take Bike 1. So the output is [0,2,1].

Note:

  1. 0 <= workers[i][j], bikes[i][j] < 1000
  2. All worker and bike locations are distinct.
  3. 1 <= workers.length <= bikes.length <= 1000

這道題用一個二維數組來表示一個校園坐標,上面有一些人和共享單車,人的數量不多余單車的數量,現在要讓每一個人都分配一輛單車,人和單車的距離是用曼哈頓距離表示的。這里的分配方法其實是有一些 confuse 的,並不是每個人要拿離其距離最近的單車,也不是每輛單車要分配給距離其最近的人,而是要從所有的 單車-人 對兒中先挑出距離最短的一對兒,然后再挑出距離第二短的組合,以此類推,直到所有的人都被分配到單車了為止。這樣的話就需要求出每一對人車距離,將所有的人車距離,和對應的人和車的標號都存到一個二維數組中。然后對這個二維數組進行排序,這里需要重寫排序規則,將人車距離小的排前面,假如距離相等,則將人標號小的放前面,假如人的標號也相同,則就將車標號小的放前面。對人車距離數組排好序之后,此時需要兩個數組來分別標記每個人被分配的車標號,和每個車的主人標號。現在從最小的人車距離開始取,若此時的人和車都沒有分配,則進行分配,遍歷完所有的人車距離之后,最終的結果就存在了標記每個人分配的車標號的數組中,參見代碼如下:


解法一:

class Solution {
public:
    vector<int> assignBikes(vector<vector<int>>& workers, vector<vector<int>>& bikes) {
        int m = workers.size(), n = bikes.size();
        vector<int> assignedWorker(m, -1), assignedBike(n, -1);
        vector<vector<int>> dist;
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                int d = abs(workers[i][0] - bikes[j][0]) + abs(workers[i][1] - bikes[j][1]);
                dist.push_back({d, i, j});
            }
        }
        sort(dist.begin(), dist.end(), [](vector<int>& a, vector<int>& b) {
                return a[0] < b[0] || (a[0] == b[0] && a[1] < b[1]) || (a[0] == b[0] && a[1] == b[1] && a[2] < b[2]);
            });
        for (auto &a : dist) {
            if (assignedWorker[a[1]] == -1 && assignedBike[a[2]] == -1) {
                assignedWorker[a[1]] = a[2];
                assignedBike[a[2]] = a[1];
            }
        }
        return assignedWorker;
    }
};

上面的解法雖然可以通過 OJ,但是並不是很高效,應該是排序的部分拖慢了速度。其實這道題的范圍是有限的,因為車和人的坐標是有限的,最大的人車距離也不會超過 2000,那么利用桶排序來做就是個不錯的選擇,只需要 2001 個桶就行了,桶中放的是 pair 對兒,其中 buckets[i] 表示距離是i的人和車的標號組成的 pair 對兒。這樣當計算出每個人車距離后,將其放入對應的桶中即可,就自動排好了序。然后開始遍歷每個桶,由於每個桶中可能不止放了一個 pair 對兒,所以需要遍歷每個桶中所有的組合,然后的操作就和上面的相同了,若此時的人和車都沒有分配,則進行分配,遍歷完所有的人車距離之后,最終的結果就存在了標記每個人分配的車標號的數組中,參見代碼如下:


解法二:

class Solution {
public:
    vector<int> assignBikes(vector<vector<int>>& workers, vector<vector<int>>& bikes) {
        int m = workers.size(), n = bikes.size();
        vector<int> assignedWorker(m, -1), assignedBike(n, -1);
        vector<vector<pair<int, int>>> buckets(2001);
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                int dist = abs(workers[i][0] - bikes[j][0]) + abs(workers[i][1] - bikes[j][1]);
                buckets[dist].push_back({i, j});
            }
        }
        for (int dist = 0; dist <= 2000; ++dist) {
            for (int k = 0; k < buckets[dist].size(); ++k) {
                if (assignedWorker[buckets[dist][k].first] == -1 && assignedBike[buckets[dist][k].second] == -1) {
                    assignedWorker[buckets[dist][k].first] = buckets[dist][k].second;
                    assignedBike[buckets[dist][k].second] = buckets[dist][k].first;
                }
            }
        }
        return assignedWorker;
    }
};

Github 同步地址:

https://github.com/grandyang/leetcode/issues/1057


類似題目:

Campus Bikes II


參考資料:

https://leetcode.com/problems/campus-bikes/

https://leetcode.com/problems/campus-bikes/discuss/305603/Java-Fully-Explained

https://leetcode.com/problems/campus-bikes/discuss/376283/Easy-C%2B%2B-solution-with-comments

https://leetcode.com/problems/campus-bikes/discuss/308738/C%2B%2B-bucket-sort-O(M*N)-time-and-space-solution


LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM