Design a simple yelp system. Support the following features:
- Add a restaurant with name and location.
- Remove a restaurant with id.
- Search the nearby restaurants by given location.
A location is represented by latitude and longitude, both in double. ALocation
class is given in code.
Nearby is defined by distance smaller thank
Km .
Restaurant
class is already provided and you can directly callRestaurant.create()
to create a new object. Also, aHelper
class is provided to calculate the distance between two location, useHelper.get_distance(location1, location2)
.
AGeoHash
class is provided to convert a location to a string. TryGeoHash.encode(location)
to convert location to a geohash string andGeoHash.decode(string)
to convert a string to location.
Notice
Learn aboutGeoHash
http://www.lintcode.com/en/help/geohash/
Have you met this question in a real interview?
Yes
Example
addRestauraunt("Lint Cafe", 10.4999999, 11.599999) // return 1
addRestauraunt("Code Cafe", 10.4999999, 11.512109) // return 2
neighbors(10.5, 11.6, 6.7) // return ["Lint Cafe"]
removeRestauraunt(1)
neighbors(10.5, 9.6, 6.7) // return []
// The distance between location(10.5, 11.6) and "Lint Code" is 0.0001099 km
// The distance between location(10.5, 11.6) and "Code Code" is 9.6120978 km
/**
* Definition of Location:
* class Location {
* public:
* double latitude, longitude;
* static Location create(double lati, double longi) {
* // This will create a new location object
* }
* };
* Definition of Restaurant
* class Restaurant {
* public:
* int id;
* string name;
* Location location;
* static Restaurant create(string &name, Location &location) {
* // This will create a new restaurant object,
* // and auto fill id
* }
* };
* Definition of Helper
* class Helper {
* public:
* static get_distance(Location &location1, Location &location2) {
* // return distance between location1 and location2.
* }
* };
* class GeoHash {
* public:
* static string encode(Location &location) {
* // return convert location to a GeoHash string
* }
* static Location decode(string &hashcode) {
* // return convert a GeoHash string to location
* }
* };
*/
struct Node {
double distance;
Restaurant restaurant;
Node(Restaurant _restaurant, double _distance) {
restaurant = _restaurant;
distance = _distance;
}
bool operator<(const Node& node) const {
return distance < node.distance;
}
};
class MiniYelp {
private:
map<int, string> id2code;
map<string, Restaurant> id2rest;
public:
MiniYelp() {
// initialize your data structure here.
}
// @param name a string
// @param location a Location
// @return an integer, restaurant's id
int addRestaurant(string name, Location &location) {
// Write your code here
Restaurant restaurant = Restaurant::create(name, location);
string hashcode = GeoHash::encode(location);
hashcode = hashcode + "." + to_string(restaurant.id);
id2code[restaurant.id] = hashcode;
id2rest[hashcode] = restaurant;
return restaurant.id;
}
// @param restaurant_id an integer
void removeRestaurant(int restaurant_id) {
// Write your code here
if (id2code.find(restaurant_id) != id2code.end()) {
id2rest.erase(id2code[restaurant_id]);
id2code.erase(restaurant_id);
}
}
// @param location a Location
// @param k an integer, distance smaller than k miles
// @return a list of restaurant's name and sort by
// distance from near to far.
vector<string> neighbors(Location &location, double k) {
// Write your code here
vector<string> res;
vector<Node> nodes;
int len = get_length(k);
string code = GeoHash::encode(location).substr(0, len);
auto it = id2rest.lower_bound(code);
for (; it != id2rest.end(); ++it) {
if (it->first.substr(0, len) != code)
break;
double distance = Helper::get_distance(it->second.location, location);
if (distance < k)
nodes.push_back(Node(it->second, distance));
}
sort(nodes.begin(), nodes.end());
for (const Node& node : nodes)
res.push_back(node.restaurant.name);
return res;
}
int get_length(double k) {
vector<double >ERROR = {2500, 630, 78, 20, 2.4, 0.61, 0.076, 0.01911, 0.00478, 0.0005971, 0.0001492, 0.0000186};
for (int i = 0; i < ERROR.size(); ++i)
if (k > ERROR[i])
return i;
return ERROR.size();
}
};