LeetCode 599: 兩個列表的最小索引總和 Minimum Index Sum of Two Lists

題目:

假設 Andy 和 Doris 想在晚餐時選擇一家餐廳,而且他們都有一個表示最喜好餐廳的列表,每一個餐廳的名字用字符串表示。javascript

Suppose Andy and Doris want to choose a restaurant for dinner, and they both have a list of favorite restaurants represented by strings.java

你須要幫助他們用最少的索引和找出他們共同喜好的餐廳。若是答案不止一個,則輸出全部答案而且不考慮順序。你能夠假設老是存在一個答案。api

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.數組

示例 1:app

輸入:
["Shogun", "Tapioca Express", "Burger King", "KFC"]
["Piatti", "The Grill at Torrey Pines", "Hungry Hunter Steakhouse", "Shogun"]
輸出: ["Shogun"]
解釋: 他們惟一共同喜好的餐廳是「Shogun」。
複製代碼

示例 2:ui

輸入:
["Shogun", "Tapioca Express", "Burger King", "KFC"]
["KFC", "Shogun", "Burger King"]
輸出: ["Shogun"]
解釋: 他們共同喜好且具備最小索引和的餐廳是「Shogun」,它有最小的索引和1(0+1)。
複製代碼

提示:spa

  1. 兩個列表的長度範圍都在 [1, 1000] 內。
  2. 兩個列表中的字符串的長度將在 [1,30] 的範圍內。
  3. 下標從 0 開始,到列表的長度減 1。
  4. 兩個列表都沒有重複的元素。

Note:rest

  1. The length of both lists will be in the range of [1, 1000].
  2. The length of strings in both lists will be in the range of [1, 30].
  3. The index is starting from 0 to the list length minus 1.
  4. No duplicates in both lists.

解題思路:

兩個字符串數組,找重複出現的元素,返回其索引和最小的目標數組。最容易想到的解法就是用哈希映射解題,Key 存儲其數組的每一個元素值,Value 存儲其下標索引。第一次遍歷將其中一個數組添加到哈希映射,第二次遍歷查找目標元素。須要維護一個最小索引和來保證查詢的目標索引和爲最小。code

哈希表解題:

Java:cdn

class Solution {
    public String[] findRestaurant(String[] list1, String[] list2) {
        Map<String, Integer> map = new HashMap<>();//創建哈希映射
        for (int i = 0; i < list1.length; i++)//初次遍歷將一個數組創建映射關係
            map.put(list1[i], i);
        List<String> res = new ArrayList<>();//待返回的目標數組
        int sum = Integer.MAX_VALUE;//sum爲當前知足條件的最小索引和
        for (int i = 0; i < list2.length; i++) {//第二次遍歷查找目標元素
            if (map.containsKey(list2[i])) {
                int tmp = i + map.get(list2[i]);//當前索引和
                if (tmp < sum) {//若是當前索引和更小
                    res.clear();//清除目標數組
                    res.add(list2[i]);//添加該元素
                    sum = tmp;// 刷新最小索引和
                } else if (tmp == sum)//若是索引和相等
                    res.add(list2[i]);//只添加元素
            }
        }
        return res.toArray(new String[res.size()]);//轉成 string 數組
    }
}
複製代碼

Python:

class Solution:
    def findRestaurant(self, list1: List[str], list2: List[str]) -> List[str]:
        hash_map = dict()# 創建哈希映射
        for i, s in enumerate(list1):# 初次遍歷將一個數組創建映射關係
            hash_map[s] = i
        min_sum = 2001# 當前知足條件的最小索引和
        res = list()# 待返回的目標數組
        for i, s in enumerate(list2):# 第二次枚舉遍歷查找目標元素
            if s in hash_map:
                tmp = i+hash_map[s]# 當前索引和
                if tmp < min_sum:# 若是當前索引和更小
                    res.clear()# 清除目標數組
                    res.append(s)# 添加該元素
                    min_sum = tmp# 刷新最小索引和
                elif tmp == min_sum:# 若是索引和相等
                    res.append(s)# 只添加元素
        return res
複製代碼

操做索引解題:

這種解法很是巧妙,雖然效率很低。如下解釋摘自 LeetCode,能夠做爲參考擴展思路:

另外一種能夠遍歷不一樣 sumsum (下標和),並判斷是否有字符串分別出如今 list1 和 list2 中且下標和爲 sum。

如今咱們知道下標和的值 sum 數值範圍從 0 到 m + n - 1。這裏 m 和 n 分別是 list1 和 list2 的長度,咱們如今能夠升序枚舉 sum ,對於每一個 sum,咱們遍歷 list1,假設當前下標爲 i,爲了獲得下標和 sum,list2 中的下標 j 爲 sum−i。經過這樣的辦法,咱們不須要遍歷 list2,而能夠直接經過計算獲得在 list2 中對應的下標。

對於每一個 sum,咱們遍歷 list1 的全部下標,一旦有 list1 和 list2 中的字符串匹配,就把匹配字符串放入一個 res 列表中。

咱們對 sum 升序數組中全部值作相同的過程,對於每一個 sum 遍歷完一遍 list1 以後,咱們檢查 res 列表是否爲空。若是是空的,咱們繼續遍歷下一個 sum 數組。若是不爲空,當前的 res 就是最小下標和的數組。這是由於咱們遍歷 sum 的順序是升序的,因此第一個找到的列表就是結果列表。

!--連接:leetcode-cn.com/problems/mi…

Java:

class Solution {
    public String[] findRestaurant(String[] list1, String[] list2) {
        List<String> res = new ArrayList<>();
        for (int sum = 0; sum < list1.length + list2.length - 1; sum++) {
            for (int i = 0; i <= sum; i++) {
                if (i < list1.length && sum - i < list2.length && list1[i].equals(list2[sum - i]))
                    res.add(list1[i]);
            }
            if (res.size() > 0) break;//一旦找到最小索引和序列直接結束遍歷,由於sum是遞增的,以後獲得的索引和必定更大
        }
        return res.toArray(new String[res.size()]);
    }
}
複製代碼

Python

class Solution:
    def findRestaurant(self, list1: List[str], list2: List[str]) -> List[str]:
        res = list()
        list1_size, list2_size = len(list1), len(list2)
        for min_sum in range(list1_size+list2_size-1):
            for i in range(min_sum+1):
                if i < list1_size and min_sum-i < list2_size and list1[i] == list2[min_sum-i]:
                    res.append(list1[i])
            if len(res) > 0:# 一旦找到最小索引和序列直接結束遍歷,由於sum是遞增的,以後獲得的索引和必定更大
                break
        return res
複製代碼

歡迎關注微。信公。衆號:愛寫Bug

愛寫Bug.png
相關文章
相關標籤/搜索