Problem statement:
Suppose Andy and Doris want to choose a restaurant for dinner, and they both have a list of favorite restaurants represented by strings.
You need to help them find out their common interest with the least list index sum. If there is a choice tie between answers, output all of them with no order requirement. You could assume there always exists an answer.
Example 1:
Input: ["Shogun", "Tapioca Express", "Burger King", "KFC"] ["Piatti", "The Grill at Torrey Pines", "Hungry Hunter Steakhouse", "Shogun"] Output: ["Shogun"] Explanation: The only restaurant they both like is "Shogun".
Example 2:
Input: ["Shogun", "Tapioca Express", "Burger King", "KFC"] ["KFC", "Shogun", "Burger King"] Output: ["Shogun"] Explanation: The restaurant they both like and have the least index sum is "Shogun" with index sum 1 (0+1).
Note:
- The length of both lists will be in the range of [1, 1000].
- The length of strings in both lists will be in the range of [1, 30].
- The index is starting from 0 to the list length minus 1.
- No duplicates in both lists.
Solution one: hash table + heap
This is the second problem of leetcode weekly contest 34. We need data structures to solve it. There is two work for us to do:
- Find the common interests ---> hash table(unordered_map)
- Find the minimal index sum among all common interests ---> heap(priority_queue).
We should redefine the heapsort function(lambda function) to return the minimal index sum
Time complexity:
- Loop for this two string lists: O(l1 + l2)
- Loop for the heap to find the minimal index sum. Since the time complexity to reheapify after one element is popped from the heap is O(klgk). k is the number of common interests.
Time complexity is O(l1 + l2) + O(klgk).
Space complexity is O(l1 + k).
class Solution { public: vector<string> findRestaurant(vector<string>& list1, vector<string>& list2) { auto comp = [](pair<int, string>& left, pair<int, string>& right){ return left.first > right.first; }; priority_queue<pair<int, string>, vector<pair<int, string>>, decltype(comp)> pq(comp); unordered_map<string, int> hash_table; // <"restaurant", index_sum> for(int i = 0; i < list1.size(); i++){ hash_table[list1[i]] = i; } for(int i = 0; i < list2.size(); i++){ if(hash_table.count(list2[i])){ pq.push({hash_table[list2[i]] + i, list2[i]}); } } vector<string> common_interests; int min_idx = pq.top().first; while(!pq.empty()){ if(pq.top().first == min_idx){ common_interests.push_back(pq.top().second); pq.pop(); } else { break; } } return common_interests; } };
Solution two: two hash tables
- Loop the first list and insert each element into the hash table index by the name of a restaurant.
- Loop the second list, if the current restaurant is a common interest and the index sum of them is:
- less than the current value, create a new item in the second hash table indexed by the index sum.
- equal to current value, push back to the solution.
Time complexity is O(l1 + l2).
Space complexity is O(l1 + k).
class Solution { public: vector<string> findRestaurant(vector<string>& list1, vector<string>& list2) { unordered_map<string, int> hash_table; // <string, index> for(int i = 0; i < list1.size(); i++){ hash_table[list1[i]] = i; } unordered_map<int, vector<string>> common_interests; int min_common = INT_MAX; string restaurant_name; for(int j = 0; j < list2.size(); j++){ if(hash_table.count(list2[j])){ if(hash_table[list2[j]] + j <= min_common){ min_common = hash_table[list2[j]] + j; restaurant_name = list2[j]; common_interests[min_common].push_back(restaurant_name); } } } return common_interests[min_common]; } };