牛客网-数据结构笔试题目(七)-k-amazing数字求解
題意
給定n個數構成的數字,我們定義一個k-amazing數的概念。如果數a同時出現在數組中所有k個連續元素構成的序列當中,并且a是其中最小的那個,那么就稱為a是一個k-amazing數字。
我們抽象一下,其實有兩個條件,第一個條件是同時出現。我們假設數組是[1, 2, 3, 4, 5],當k=3時,我們可以找到的序列是[1, 2, 3], [2, 3, 3], [3, 4, 5]。這三個序列當中的共有元素是3,并且只有3,所以3就是一個k-amazing數。第二個條件是最小,如果這樣的數字可以找到多個,只有最小的那個數字才是k-amazing數。
現在給定數組a,要求所有的1-n的k-amazing數。
樣例
題解
這道題的題意倒是挺明確的,沒什么含糊不清的情況。但是我們分析一下會發現,想要順著題意去解決是不可能的。因為我們沒有什么特別好的方法可以快速尋找多個集合當中的交集,并且查詢到交集之后還需要分析交集當中的最小值。
也嘗試過引入線段樹或者是樹狀數組等數據結構,依然一無所獲。最后能夠解出來其實挺取巧的,是因為注意到了一個細節,這個細節就是元素的范圍,題目當中給定的是
。這和我們以往的題目都不太一樣,一般來說都會給定一個具體的值作為范圍,而不是給定一個變量。
如果有過一定算法題基礎和經驗的同學,注意到這個應該能想到桶排序或者是基數排序。如果我們保證所有的元素都小于數組的長度,那么我們可以用一種很取巧的方式來完成排序。
我們直接來看代碼:
這個算法的復雜度是
,要比一般的排序算法更快,因為我們利用了下標的天然有序性。順著這條線我想到了問題的關鍵,發現我們一開始的思路其實走入了誤區。
思維誤區與提示
這道題最大的trick就是我們對于算法的初印象,我一直在想一種方法可以快速地根據k求出k-amazing數。然后我發現情況非常復雜,并且涉及到集合的處理,比較麻煩。
這道題需要我們反其道而行之,并不是根據k去尋找k-amazing數,而是根據一個數在數組當中出現的分布,來判斷它可以構成什么k-amazing。這也是為什么所有出現的數要小于n的原因,并不是說一定要小于n才有解,而是為了給我們一個思維提示。
我簡單來解釋一下這其中的原理,大家立刻就明白了,其實非常非常簡單,有點像是魔術師用很簡單的障眼法欺騙了我們的感覺。
我們假設上面這條線是題目給定的數組,我們假設其中某一個數m出現了3次,分別是a1, a2和a3。那么請問,如果m是一個k-amazing數,這個k應該至少是多大?
很簡單,應該是
,我們肉眼觀察一下應該是a2-a1,那么我們畫出來應該是這樣的:
其實就是簡單的區間覆蓋問題,如果k小于這個值,那么a1到a2中間的部分一定無法滿足。你可能還是會覺得有問題,不對啊,我們要找的是最小值,你怎么能知道這個m是不是最小的呢?
這個問題也非常簡單,我們只需要按照順序從小到大去尋找k,那么第一個找到的一定就是答案。想明白了之后有沒有醍醐灌頂,有沒有豁然開朗的感覺?是不是還有我居然想到了,又有一點覺得自己早就應該想到了的矛盾感?這也是做算法題的樂趣所在,所謂的難者不會,會者不難,體現得淋漓盡致。
不過還有一個小trick,有可能對于有些k我們找不到答案,但是它并不一定不存在。這也很好理解,我們假設找到了k=3時的答案是m,我們沒有直接找到間隔是4的數,那么問題來了,m滿不滿足k=4呢?當然是滿足的,因為小的間隔都能成立,大的間隔一定也可以。
最后,貼上代碼:
這題非常有趣,強烈建議大家都試著做一下。
總結
以上是生活随笔為你收集整理的牛客网-数据结构笔试题目(七)-k-amazing数字求解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 少儿编程150讲轻松学Scratch(十
- 下一篇: 牛客网-数据结构笔试题目(八)-离子能力