日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

牛客网-数据结构笔试题目(七)-k-amazing数字求解

發布時間:2023/12/2 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 牛客网-数据结构笔试题目(七)-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數。

樣例

題解

這道題的題意倒是挺明確的,沒什么含糊不清的情況。但是我們分析一下會發現,想要順著題意去解決是不可能的。因為我們沒有什么特別好的方法可以快速尋找多個集合當中的交集,并且查詢到交集之后還需要分析交集當中的最小值。
也嘗試過引入線段樹或者是樹狀數組等數據結構,依然一無所獲。最后能夠解出來其實挺取巧的,是因為注意到了一個細節,這個細節就是元素的范圍,題目當中給定的是
。這和我們以往的題目都不太一樣,一般來說都會給定一個具體的值作為范圍,而不是給定一個變量。
如果有過一定算法題基礎和經驗的同學,注意到這個應該能想到桶排序或者是基數排序。如果我們保證所有的元素都小于數組的長度,那么我們可以用一種很取巧的方式來完成排序。
我們直接來看代碼:

a = [4, 3, 2, 5, 1] ret = [] base = [0 for _ in range(6)]for i in a:base[i] += 1for i in range(6):if base[i] > 0:for j in range(base[i]):ret.append(i)

這個算法的復雜度是
,要比一般的排序算法更快,因為我們利用了下標的天然有序性。順著這條線我想到了問題的關鍵,發現我們一開始的思路其實走入了誤區。

思維誤區與提示

這道題最大的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呢?當然是滿足的,因為小的間隔都能成立,大的間隔一定也可以。
最后,貼上代碼:

from collections import defaultdictt = int(input())for _ in range(t):n = int(input())arr = list(map(int, input().split(' ')))# 我們要記錄元素的出現位置,會有多個,所以要用map[int]list的結構dt = defaultdict(list)for i, v in enumerate(arr):dt[v].append(i)ret = [-1 for _ in range(n+2)]for i in range(1, n+1):if i not in dt:continue# 由于下標是0開始的,所以第一段區間長度是下標+1tmp = dt[i][0] + 1# 尋找元素i出現的最大間隔for idx in range(1, len(dt[i])):tmp = max(tmp, dt[i][idx] - dt[i][idx-1])tmp = max(tmp, n - dt[i][-1])# 如果這個長度的答案沒有出現過,就賦值if ret[tmp] == -1:ret[tmp] = i# 如果m是k-amazing數,那么它也是k+1-amazing數for i in range(2, n+1):if ret[i-1] == -1:continueif ret[i] == -1 or ret[i] > ret[i-1]:ret[i] = ret[i-1]print(' '.join(map(str, ret[1: n+1])))

這題非常有趣,強烈建議大家都試著做一下。

總結

以上是生活随笔為你收集整理的牛客网-数据结构笔试题目(七)-k-amazing数字求解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。