天天看點

LintCode 280: Closest City

280. Closest City

There are many cities on a two-dimensional plane, all cities have their own names c[i]c[i], and location coordinates (x[i],y[i])(x[i],y[i]) (both are integers). There are qq group queries, and each group query gives a city name. You need to answer the city name that is the closest to the city and has the same xx or yy.

Example

Example 1:

Input: x = [3, 2, 1] y = [3, 2, 3] c = ["c1", "c2", "c3"] q = ["c1", "c2", "c3"]

Output: ["c3", "NONE", "c1"]

Explanation: For c1, c3 is the same as its y, the closest distance is (3-1)+(3-3)=2

For c2, no city is the same as its x or y

For c3, c1 is the same as his y, the closest distance is (3-1)+(3-3)=2

Notice

If there are multiple answers that satisfy the conditions, the one with the smallest lexicographic name is output.

The distance here is the Euler distance: the absolute value of the coordinate difference of xx plus the absolute value of the coordinate difference of yy.

0 ≤ Number of cities ≤ 10^5, 

0 ≤ Ask for the number of groups ≤ 10, 

1 ≤ Coordinate range 10^9

​​ 解法1:

這題被辨別為簡單,但我覺得其實做出來挺花時間。

我的解法是把每個X和Y坐标都建一個vector數組,裝在這個X或Y坐标上的城市清單。然後排序。對于query數組,找到這個城市在對應X和Y坐标上的位置,然後前後找對應的鄰近城市,然後比較大小。

注意:

1) for (auto & elem : x_cities) 和 for (auto & elem : y_cities) 要加引用,因為内部x_cities和y_cities排序,産生了變化。

2) 當比較大小是相等時,用字典排序。

這個解法時間複雜度是O(nlogn),效率不高。

class Solution {
public:
    /**
     * @param x: an array of integers, the x coordinates of each city[i]
     * @param y: an array of integers, the y coordinates of each city[i]
     * @param c: an array of strings that represent the names of each city[i]
     * @param q: an array of strings that represent the names of query locations
     * @return: the closest city for each query
     */
    vector<string> NearestNeighbor(vector<int> &x, vector<int> &y, vector<string> &c, vector<string> &q) {
        int n = x.size();
        vector<string> result;
        unordered_map<int, vector<pair<int, string>>> x_cities;  //x->list of (y, city)
        unordered_map<int, vector<pair<int, string>>> y_cities;  //y->list of (x, city)
        
        unordered_map<string, int> city_x; //city->x
        unordered_map<string, int> city_y; //city->y
        
        for (int i = 0; i < n; ++i) {
            x_cities[x[i]].push_back({y[i], c[i]});
            city_x[c[i]] = x[i];
        }
        
        for (int i = 0; i < n; ++i) {
            y_cities[y[i]].push_back({x[i], c[i]});
            city_y[c[i]] = y[i];
        }
        
        for (auto &elem : x_cities) { //注意加引用
            sort(elem.second.begin(), elem.second.end()); //sort y values under the same x
        }

        for (auto &elem : y_cities) { //注意加引用
            sort(elem.second.begin(), elem.second.end()); //sort x values under the same y
        }

        for (int i = 0; i < q.size(); ++i) {
           int min_dist = INT_MAX;
            string closest_city = "NONE";
            int target_x = city_x[q[i]];
            int target_y = city_y[q[i]];
            int dist = 0;
            if (x_cities[target_x].size() > 1) {
                int find_y_index = binary_search(x_cities[target_x], target_y);
                if (find_y_index != -1) { //one city does not need to search
                    if (find_y_index > 0) {
                        dist = x_cities[target_x][find_y_index].first - x_cities[target_x][find_y_index - 1].first;
                        if (min_dist > dist || (min_dist == dist && x_cities[target_x][find_y_index - 1].second < closest_city)) {
                            min_dist = dist;
                            closest_city = x_cities[target_x][find_y_index - 1].second;
                        }
                    }
                    if (find_y_index < x_cities[target_x].size() - 1) {
                        dist = x_cities[target_x][find_y_index + 1].first - x_cities[target_x][find_y_index].first;
                        if (min_dist > dist || (min_dist == dist && x_cities[target_x][find_y_index + 1].second < closest_city)) {
                            min_dist = dist;
                            closest_city = x_cities[target_x][find_y_index + 1].second;
                        }
                    }
                }
            }
            
            if (y_cities[target_y].size() > 1) { //one city does not need to search
                int find_x_index = binary_search(y_cities[target_y], target_x);
                if (find_x_index != -1) {    
                    if (find_x_index > 0) {
                        dist = y_cities[target_y][find_x_index].first - y_cities[target_y][find_x_index - 1].first;
                        if (min_dist > dist || (min_dist == dist && y_cities[target_y][find_x_index - 1].second < closest_city)) {
                            min_dist = dist;
                            closest_city = y_cities[target_y][find_x_index - 1].second;
                        }
                    }
                    if (find_x_index < y_cities[target_y].size() - 1) {
                        dist = y_cities[target_y][find_x_index + 1].first - y_cities[target_y][find_x_index].first;
                        if (min_dist > dist || min_dist == dist && y_cities[target_y][find_x_index + 1].second < closest_city) {
                            min_dist = dist;
                            closest_city = y_cities[target_y][find_x_index + 1].second;
                        }
                    }
                }
            }
            result.push_back(closest_city);
        }
        
        return result;
    }
    
private:
    int binary_search(vector<pair<int, string>> arr, int target) {
        int start = 0, end = arr.size() - 1;
        
        while(start + 1 < end) {
            int mid = start + (end - start) / 2;
            if (arr[mid].first < target) {
                start = mid;
            } else if (arr[mid].first > target) {
                end = mid;
            } else {
                return mid;
            }
        }
        
        if (arr[end].first == target) return end;
        if (arr[start].first == target) return start;
        return -1;
    }
};
           

解法2:直接硬比。時間複雜度O(mn)。

class Solution {
public:
    /**
     * @param x: an array of integers, the x coordinates of each city[i]
     * @param y: an array of integers, the y coordinates of each city[i]
     * @param c: an array of strings that represent the names of each city[i]
     * @param q: an array of strings that represent the names of query locations
     * @return: the closest city for each query
     */
    vector<string> NearestNeighbor(vector<int> &x, vector<int> &y, vector<string> &c, vector<string> &q) {
        int cx, cy;
        vector <string> near;
        for(int queryIndex = 0; queryIndex < q.size(); queryIndex++)
        {
            string city = "NONE";
            int minDistance = 0;
            int findIndex = 0;             
            for(int i = 0; i < c.size(); i++)
            {
                if(c[i] == q[queryIndex])
                {
                    cx = x[i];
                    cy = y[i];
                    findIndex = i;
                    break;
                }
            }
            
            for(int i = 0; i < c.size(); i++)
            {
                if(i == findIndex)
                {
                    continue;
                }
                
                if(x[i] == cx)
                {
                    if(abs(cy - y[i]) < minDistance || minDistance == 0)
                    {
                        minDistance = abs(cy - y[i]);
                        city = c[i];
                    }
                    if(abs(cy - y[i]) == minDistance && c[i] < city)
                    {
                        minDistance = abs(cy - y[i]);
                        city = c[i];
                    }
                }
                
                if(y[i] == cy)
                {
                    if(abs(cx - x[i]) < minDistance || minDistance == 0)
                    {
                        minDistance = abs(cx - x[i]);
                        city = c[i];
                    }
                    
                    if(abs(cx - x[i]) == minDistance && c[i] < city)
                    {
                        minDistance = abs(cx - x[i]);
                        city = c[i];
                    }
                }
             }
            
            near.push_back(city);
        
        }
        return near;
    }
};
           

繼續閱讀