Welcome to Subscribe On Youtube
  • import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Map.Entry;
    
    
    /*
    
    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.
    
    
     */
    
    public class Minimum_Index_Sum_of_Two_Lists {
    
    	public static void main(String[] args) {
    		Minimum_Index_Sum_of_Two_Lists out = new Minimum_Index_Sum_of_Two_Lists();
    		Solution s = out.new Solution();
    
    		String[] s1 = new String[]{"Shogun","Tapioca Express","Burger King","KFC"};
    		String[] s2 = new String[]{"KFC","Burger King","Tapioca Express","Shogun"};
    		System.out.println(Arrays.toString(s.findRestaurant(s1, s2)));
    
    		Solution2 sl2 = out.new Solution2();
    
    		String[] s21 = new String[]{"Shogun","Tapioca Express","Burger King","KFC"};
    		String[] s22 = new String[]{"KFC","Burger King","Tapioca Express","Shogun"};
    		System.out.println(Arrays.toString(sl2.findRestaurant(s21, s22)));
    	}
    
        // o(n^2)
    	public class Solution {
    	    public String[] findRestaurant(String[] list1, String[] list2) {
    	        if (list1 == null || list2 == null || list1.length == 0 || list2.length == 0) {
    	            return new String[]{""};
    	        }
    
    	        // maintain 2 indexes, both pointing to the same restaurant
    	        int index1 = -1; // minus: not-found
    	        int index2 = -1;
    	        int min = Integer.MAX_VALUE;
    	        ArrayList<String> restaurant = new ArrayList<String>(30); // length of strings 1-30
    
    	        for (int i = 0; i < list1.length; i++) {
    	            for (int j = 0; j < list2.length; j++) {
    	                if (list1[i].equals(list2[j]) && (i + j < min)) {
    	                    // record indexes
    	                    min = i + j;
    	                    restaurant = new ArrayList<String>(30);
    	                    restaurant.add(list1[i]);
    	                } else if (list1[i].equals(list2[j]) && (i + j == min)) {
    	                    // choice tie, then print all of them
    	                    restaurant.add(list1[i]);
    	                }
    	            }
    	        }
    
    	        return restaurant.toArray(new String[restaurant.size()]);
    
    	        // @note: below has runtime error: java.lang.ClassCastException: [Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
    	        //return (String[]) restaurant.toArray();
    	    }
    	}
    
    	// o(m+n), extra space
    	public class Solution2 {
    	    public String[] findRestaurant(String[] list1, String[] list2) {
    	        if (list1 == null || list2 == null || list1.length == 0 || list2.length == 0) {
    	            return new String[]{""};
    	        }
    
    	        // maintain 2 indexes, both pointing to the same restaurant
    	        int index1 = -1; // minus: not-found
    	        int index2 = -1;
    	        int min = Integer.MAX_VALUE;
    	        ArrayList<String> restaurant = new ArrayList<String>(30); // length of strings 1-30
    
    	        // @note: use 2 hashmap: 1.store name => index, 2.store sumIndex => word
    
    	        // store list1 for o(1) access
    	        HashMap<String, Integer> hmList1 = new HashMap<>();
    	        for (int i = 0; i < list1.length; i++) {
    	            hmList1.put(list1[i], i);
    	        }
    
    	        // store sumIndex => word
    	        int minIndex = Integer.MAX_VALUE;
    	        for (int j = 0; j < list2.length; j++) {
    	            if (hmList1.containsKey(list2[j])) {
    	                // common interest
    	                int sum = j + hmList1.get(list2[j]);
    		            if (sum < minIndex) {
    		            	minIndex = sum; // update minIndex
    
    		            	restaurant = new ArrayList<String>(30);
    		            	restaurant.add(list2[j]);
    		            } else if (sum == minIndex) {
    		            	restaurant.add(list2[j]);
    		            }
    	            }
    	        }
    
    	        return restaurant.toArray(new String[restaurant.size()]);
    	    }
    	}
    }
    
    ############
    
    class Solution {
        public String[] findRestaurant(String[] list1, String[] list2) {
            Map<String, Integer> mp = new HashMap<>();
            for (int i = 0; i < list2.length; ++i) {
                mp.put(list2[i], i);
            }
            List<String> ans = new ArrayList<>();
            int mi = 2000;
            for (int i = 0; i < list1.length; ++i) {
                if (mp.containsKey(list1[i])) {
                    int t = i + mp.get(list1[i]);
                    if (t < mi) {
                        ans = new ArrayList<>();
                        ans.add(list1[i]);
                        mi = t;
                    } else if (t == mi) {
                        ans.add(list1[i]);
                    }
                }
            }
            return ans.toArray(new String[0]);
        }
    }
    
  • // OJ: https://leetcode.com/problems/minimum-index-sum-of-two-lists/
    // Time: O(L1 + L2)
    // Space: O(L1)
    class Solution {
    public:
        vector<string> findRestaurant(vector<string>& list1, vector<string>& list2) {
            unordered_map<string, int> m;
            for (int i = 0; i < list1.size(); ++i) m[list1[i]] = i;
            int minSum = INT_MAX;
            vector<string> ans;
            for (int i = 0; i < list2.size() && i <= minSum; ++i) {
                if (m.find(list2[i]) == m.end() || i + m[list2[i]] > minSum) continue;
                if (i + m[list2[i]] < minSum) {
                    ans.clear();
                    minSum = i + m[list2[i]];
                }
                ans.push_back(list2[i]);
            }
            return ans;
        }
    };
    
  • class Solution:
        def findRestaurant(self, list1: List[str], list2: List[str]) -> List[str]:
            ans = []
            mp = {v: i for i, v in enumerate(list2)}
            mi = 2000
            for i, v in enumerate(list1):
                if v in mp:
                    t = i + mp[v]
                    if t < mi:
                        mi = t
                        ans = [v]
                    elif t == mi:
                        ans.append(v)
            return ans
    
    ############
    
    class Solution(object):
      def findRestaurant(self, list1, list2):
        """
        :type list1: List[str]
        :type list2: List[str]
        :rtype: List[str]
        """
        minSum = float("inf")
        ans = []
        d = {}
        for i, name in enumerate(list2):
          d[name] = i
        for i, name in enumerate(list1):
          idxSum = i + d.get(name, float("inf"))
          if idxSum == minSum:
            ans.append(name)
          if idxSum < minSum:
            ans = [name]
            minSum = idxSum
        return ans
    
    
  • func findRestaurant(list1 []string, list2 []string) []string {
    	mp := make(map[string]int)
    	for i, v := range list2 {
    		mp[v] = i
    	}
    	mi := 2000
    	var ans []string
    	for i, v := range list1 {
    		if _, ok := mp[v]; ok {
    			t := i + mp[v]
    			if t < mi {
    				ans = []string{v}
    				mi = t
    			} else if t == mi {
    				ans = append(ans, v)
    			}
    		}
    	}
    	return ans
    }
    
  • function findRestaurant(list1: string[], list2: string[]): string[] {
        let minI = Infinity;
        const res = [];
        const map = new Map<string, number>(list1.map((s, i) => [s, i]));
        list2.forEach((s, i) => {
            if (map.has(s)) {
                const sumI = i + map.get(s);
                if (sumI <= minI) {
                    if (sumI < minI) {
                        minI = sumI;
                        res.length = 0;
                    }
                    res.push(s);
                }
            }
        });
        return res;
    }
    
    
  • use std::collections::HashMap;
    use std::iter::FromIterator;
    
    impl Solution {
        pub fn find_restaurant(list1: Vec<String>, list2: Vec<String>) -> Vec<String> {
            let map: HashMap<String, usize> = HashMap::from_iter(list1.into_iter().zip(0..));
            let mut res = vec![];
            let mut min_i = usize::MAX;
            list2.into_iter().enumerate().for_each(|(i, key)| {
                if map.contains_key(&key) {
                    let sum_i = map.get(&key).unwrap() + i;
                    if sum_i <= min_i {
                        if (sum_i < min_i) {
                            min_i = sum_i;
                            res.clear();
                        }
                        res.push(key);
                    }
                }
            });
            res
        }
    }
    
    
  • class Solution {
        public String[] findRestaurant(String[] list1, String[] list2) {
            int length1 = list1.length, length2 = list2.length;
            int leastIndexSum = Integer.MAX_VALUE;
            Map<String, Integer> list1Map = new HashMap<String, Integer>();
            Map<Integer, List<String>> indexSumInterestMap = new HashMap<Integer, List<String>>();
            for (int i = 0; i < length1; i++)
                list1Map.put(list1[i], i);
            for (int i = 0; i < length2; i++) {
                String interest = list2[i];
                if (!list1Map.containsKey(interest))
                    continue;
                int indexSum = list1Map.get(interest) + i;
                List<String> interests = indexSumInterestMap.getOrDefault(indexSum, new ArrayList<String>());
                interests.add(interest);
                indexSumInterestMap.put(indexSum, interests);
                if (indexSum < leastIndexSum)
                    leastIndexSum = indexSum;
            }
            List<String> interestsList = indexSumInterestMap.getOrDefault(leastIndexSum, new ArrayList<String>());
            int length = interestsList.size();
            String[] interests = new String[length];
            for (int i = 0; i < length; i++)
                interests[i] = interestsList.get(i);
            return interests;
        }
    }
    
    ############
    
    class Solution {
        public String[] findRestaurant(String[] list1, String[] list2) {
            Map<String, Integer> mp = new HashMap<>();
            for (int i = 0; i < list2.length; ++i) {
                mp.put(list2[i], i);
            }
            List<String> ans = new ArrayList<>();
            int mi = 2000;
            for (int i = 0; i < list1.length; ++i) {
                if (mp.containsKey(list1[i])) {
                    int t = i + mp.get(list1[i]);
                    if (t < mi) {
                        ans = new ArrayList<>();
                        ans.add(list1[i]);
                        mi = t;
                    } else if (t == mi) {
                        ans.add(list1[i]);
                    }
                }
            }
            return ans.toArray(new String[0]);
        }
    }
    
  • // OJ: https://leetcode.com/problems/minimum-index-sum-of-two-lists/
    // Time: O(L1 + L2)
    // Space: O(L1)
    class Solution {
    public:
        vector<string> findRestaurant(vector<string>& list1, vector<string>& list2) {
            unordered_map<string, int> m;
            for (int i = 0; i < list1.size(); ++i) m[list1[i]] = i;
            int minSum = INT_MAX;
            vector<string> ans;
            for (int i = 0; i < list2.size() && i <= minSum; ++i) {
                if (m.find(list2[i]) == m.end() || i + m[list2[i]] > minSum) continue;
                if (i + m[list2[i]] < minSum) {
                    ans.clear();
                    minSum = i + m[list2[i]];
                }
                ans.push_back(list2[i]);
            }
            return ans;
        }
    };
    
  • class Solution:
        def findRestaurant(self, list1: List[str], list2: List[str]) -> List[str]:
            ans = []
            mp = {v: i for i, v in enumerate(list2)}
            mi = 2000
            for i, v in enumerate(list1):
                if v in mp:
                    t = i + mp[v]
                    if t < mi:
                        mi = t
                        ans = [v]
                    elif t == mi:
                        ans.append(v)
            return ans
    
    ############
    
    class Solution(object):
      def findRestaurant(self, list1, list2):
        """
        :type list1: List[str]
        :type list2: List[str]
        :rtype: List[str]
        """
        minSum = float("inf")
        ans = []
        d = {}
        for i, name in enumerate(list2):
          d[name] = i
        for i, name in enumerate(list1):
          idxSum = i + d.get(name, float("inf"))
          if idxSum == minSum:
            ans.append(name)
          if idxSum < minSum:
            ans = [name]
            minSum = idxSum
        return ans
    
    
  • func findRestaurant(list1 []string, list2 []string) []string {
    	mp := make(map[string]int)
    	for i, v := range list2 {
    		mp[v] = i
    	}
    	mi := 2000
    	var ans []string
    	for i, v := range list1 {
    		if _, ok := mp[v]; ok {
    			t := i + mp[v]
    			if t < mi {
    				ans = []string{v}
    				mi = t
    			} else if t == mi {
    				ans = append(ans, v)
    			}
    		}
    	}
    	return ans
    }
    
  • function findRestaurant(list1: string[], list2: string[]): string[] {
        let minI = Infinity;
        const res = [];
        const map = new Map<string, number>(list1.map((s, i) => [s, i]));
        list2.forEach((s, i) => {
            if (map.has(s)) {
                const sumI = i + map.get(s);
                if (sumI <= minI) {
                    if (sumI < minI) {
                        minI = sumI;
                        res.length = 0;
                    }
                    res.push(s);
                }
            }
        });
        return res;
    }
    
    
  • use std::collections::HashMap;
    use std::iter::FromIterator;
    
    impl Solution {
        pub fn find_restaurant(list1: Vec<String>, list2: Vec<String>) -> Vec<String> {
            let map: HashMap<String, usize> = HashMap::from_iter(list1.into_iter().zip(0..));
            let mut res = vec![];
            let mut min_i = usize::MAX;
            list2.into_iter().enumerate().for_each(|(i, key)| {
                if map.contains_key(&key) {
                    let sum_i = map.get(&key).unwrap() + i;
                    if sum_i <= min_i {
                        if (sum_i < min_i) {
                            min_i = sum_i;
                            res.clear();
                        }
                        res.push(key);
                    }
                }
            });
            res
        }
    }
    
    

All Problems

All Solutions