刷穿劍指offer-Day16-哈希表III 哈希表的總結與題型擴展!

昨日回顧

昨天,我們針對Java中的 HashMap 、HashSet ,和Python中的 dict & set 使用,進行了分類學習,并按照表格總結了不同數據結構所包含的方法與使用場景。在這兩個數據結構上,Python與Java倒是大同小異,沒有過多的差別。

之后,通過兩道題目簡單了解了這類題型的解題方式。那么今天,我們在此基礎上進一步來熟悉下哈希表解題的運用。

先來一道閱讀理解題目熱熱身子吧!

劍指OfferII034.外星語言是否排序

https://leetcode-cn.com/problems/lwyVBB/solution/shua-chuan-jian-zhi-offer-day16-ha-xi-bi-mtik/

難度:簡單

題目:

某種外星語也使用英文小寫字母,但可能順序 order 不同。字母表的順序(order)是一些小寫字母的排列。

給定一組用外星語書寫的單詞 words,以及其字母表的順序 order,只有當給定的單詞在這種外星語中按字典序排列時,
返回 true;否則,返回 false。

提示:

  • 1 <= words.length <= 100
  • 1 <= words[i].length <= 20
  • order.length == 26
  • 在 words[i] 和 order 中的所有字符都是英文小寫字母。

示例:

示例 1:
輸入:words = ["hello","leetcode"], order = "hlabcdefgijkmnopqrstuvwxyz"
輸出:true
解釋:在該語言的字母表中,'h' 位于 'l' 之前,所以單詞序列是按字典序排列的。

示例 2:
輸入:words = ["word","world","row"], order = "worldabcefghijkmnpqstuvxyz"
輸出:false
解釋:在該語言的字母表中,'d' 位于 'l' 之后,那么 words[0] > words[1],因此單詞序列不是按字典序排列的。

示例 3:
輸入:words = ["apple","app"], order = "abcdefghijklmnopqrstuvwxyz"
輸出:false
解釋:當前三個字符 "app" 匹配時,第二個字符串相對短一些,然后根據詞典編纂規則 "apple" > "app",
因為 'l' > '?',其中 '?' 是空白字符,定義為比任何其他字符都小(更多信息)。

分析

坦白說這是一道閱讀理解題目,能仔細看清楚題目要求的比較規則,就差不多已經通過了...
根據外星人的英文字母順序,比較words列表中的每個單詞是按照 升序 排列的,則返回 true ,否則返回 false
那么如何比較每個單詞的順序呢?通過觀察示例,我們了解到其實就是針對單詞去按位比較,在order中的順序。
這里注意下,如果長度不夠,以空補充,空即無窮小。
理解了上面的思路,就可以開始編寫解題了:

  1. 比較單詞的出現順序,可以用到哈希表去快速獲取單詞的排序下標,既然是哈希表專題,就不用ascii配合數組模擬哈希了。
  2. 然后就要開始單詞的逐個比較了,這個可以參考冒泡排序的方式兩兩比較,a<b且b<c,則肯定a < c
  3. 如果遇到left[index] > right[index] 直接返回False,無需其他操作了
  4. 如果遇到left[index] < right[index] 類似 109 < 110 十位已經小了,后面就沒必要看了,直接break接著比較下一個。
  5. 如果第三步一直沒有false,最終返回true即可。

來看看具體解題吧:

解題:

Python:

class Solution:
    def isAlienSorted(self, words: List[str], order: str) -> bool:
        dic = {j: i for i, j in enumerate(order)}
        for i in range(len(words) - 1):
            w1, w1_len = words[i], len(words[i])
            w2, w2_len = words[i + 1], len(words[i + 1])
            for idx in range(max(w1_len, w2_len)):
                w1_idx = -1 if idx >= w1_len else dic[w1[idx]]
                w2_idx = -1 if idx >= w2_len else dic[w2[idx]]
                if w1_idx > w2_idx:
                    return False
                if w1_idx < w2_idx:
                    break
        return True

Java:

class Solution {
    public boolean isAlienSorted(String[] words, String order) {
        HashMap<Character, Integer> map = new HashMap<>();
        for (int i = 0; i < order.length(); i++) {
            map.put(order.charAt(i), i);
        }
        for (int i = 0; i < words.length - 1; i++) {
            String w1 = words[i];
            int w1_len = w1.length();
            String w2 = words[i + 1];
            int w2_len = w2.length();
            for (int j = 0; j < Math.max(w1_len, w2_len); j++) {
                int idx_w1 = j > w1_len ? -1 : map.get(w1.charAt(j));
                int idx_w2 = j > w2_len ? -1 : map.get(w2.charAt(j));
                if (idx_w1 > idx_w2) return false;
                if (idx_w1 < idx_w2) break;
            }
        }
        return true;
    }
}

這道閱讀理解的題目,是不是一下子把自信就給找回來了?

雖然說哈希表是算法中最常用的數據結構,但是它卻比較比較簡單而純粹,當你需要優化時間的時候,就使用它來把時間轉換為空間。就是這么簡單....

注意:但下面我要不按套路出牌的給大家分享一道很特別的哈希表題目了,快來看看吧。

525.連續數組

https://leetcode-cn.com/problems/contiguous-array/solution/525lian-xu-shu-zu-qian-zhui-he-hashbiao-riqe2/

難度:中等

題目:

給定一個二進制數組 nums , 找到含有相同數量的 0 和 1 的最長連續子數組,
并返回該子數組的長度。

示例:

示例 1:
輸入: nums = [0,1]
輸出: 2
說明: [0, 1] 是具有相同數量0和1的最長連續子數組。

示例 2:
輸入: nums = [0,1,0]
輸出: 2
說明: [0, 1] (或 [1, 0]) 是具有相同數量0和1的最長連續子數組。

示例 3:
輸入: nums = [0,0,1,0,0,0,1,1]
輸出: 6
說明: [1,0,0,0,1,1] 是具有相同數量0和1的最長連續子數組。

分析

不得不說,如果這道題的用例是-1 和 1,那么大家可能還比較容易產生思路,可惜這道題是0 和 1,我們需要轉化一下

為什么要轉化為-1 和 1呢?

因為如果具有相同的-1 和 1,由于它們數目相同,所以這些數字加起來就等于0。
加起來,看到這個關鍵字是不是該想到我們在數組中學習到的前綴和了?

我們采用前綴的方式,當前綴和的某一個數和之前的某一個位置的數字相等,那是不是在這段數組之間出現了相同數目的-1 和 1,所以抵消為0 了。

配合Hash表的使用,我們可以快速記錄 {前綴和: 下標} 的關系, 由于可能存在nums前N數字和剛好滿足條件的情況,所以我們預制燒餅節點{0,-1},來規避該問題。

循環判斷是否在字典中存在前綴和一樣的鍵,并不斷判斷最長符合題意的連續數組,最終返回即可。

千言萬語化作一張圖,一看就明白了:

在index = 7的位置前綴和為 -2, 而哈希表中在index = 1的位置前綴和也為-2。這便是我們通過前綴和+哈希表來解題的思路了。

解題:

Python:

class Solution:
    def findMaxLength(self, nums):
        d = {0: -1}
        ret = pre_sum = 0
        for i, num in enumerate(nums):
            pre_sum += 1 if num == 1 else -1
            pre_index = d.get(pre_sum, i)
            if pre_index == i:
                d[pre_sum] = i
            else:
                ret = max(ret, i - pre_index)
        return ret

Java:

class Solution {
    public int findMaxLength(int[] nums) {
        HashMap<Integer, Integer> map = new HashMap<>();
        map.put(0, -1);
        int pre_sum = 0;
        int ret = 0;
        for (int i = 0; i < nums.length; i++) {
            pre_sum += nums[i] == 1 ? 1 : -1;
            int pre_index = map.getOrDefault(pre_sum, i);
            if (pre_index == i) {
                map.put(pre_sum, i);
            } else {
                ret = Math.max(ret, i - pre_index);
            }
        }
        return ret;
    }
}

個人感覺 525.連續數組 是一道比較綜合的算法題目,涉及到我們之前學習的前綴思維,與本章的哈希表的結合。

反倒是 劍指 Offer II 035. 最小時間差 作為哈希表的最后一道題顯得有些不倫不類。所以這道題就留給大家作為課后作業了。

哈希表的章節就到這里了,讓我們一路向前吧!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,117評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,860評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,128評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,291評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,025評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,421評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,477評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,642評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,177評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,970評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,157評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,717評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,410評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,821評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,053評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,896評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,157評論 2 375

推薦閱讀更多精彩內容