昨天剛做的拼多多筆試題,說一下題解思路,第三題開始沒什麼時間寫了,所以沒提交,不知道能不能全ac。第
三、四題,可以僅當做思路,因為是做完才想明白的。
第一題:給兩個陣列l1,l2,乙個提前量offset,乙個數字n。l1,l2是商品列表,offset是已經展示過的商品數量,n是要求展示的商品數量,輸出要展示的商品在l1,l2裡的區間,左閉右開。
例如l1=4,l2=4,offset=2,n=4。l1已經有兩個展示過了,所以l1商品區間為(2,4);l2為(0:2)。如果有列表被跳過(也就是offset>l1的長度),區間兩個數字用該列表長度代替,若果有列表不需要商品展示(offset+n考察陣列,很簡單,輸出要求的陣列區間即可,需要弄明白的就是幾個邊界條件而已。
第二題:給乙個n,n是商品的數量,再給乙個大小為n的陣列,陣列元素值表示商品的**,買三個,其中**最低的免費。輸出購買所有商品需要的金額。例如 6 7 8 5,輸出20
貪心策略,先對**按降序排序,遞推,每遇到第三個,總金額不動,其他都加商品**就可以了。
第三題:給出n,k,再給出乙個大小為n的一串數字(每個數字【0,9】)。目的是將這個陣列變為至少有k個數字相同的新陣列,並且變化過程中,差值要最小,如果有好幾種方案,輸出字典序最小的。例如n=6,k=5,數字串:787585,答案是777577,差值為4.答案有777577和777775兩種,第一種字典序最小。
解決方法:先將數字串裡數字出現的次數記錄下來,先建立乙個大小為10的陣列,arr=[0]*10。787585,下標為7,8,5各兩個。
第一步,選中要成為k次的那個數字target,從大到小進行迴圈,對於787585分別是8,7,5,此時我們需要變動k-arr[target]次。為什麼要從大到小呢,因為答案要字典序最小,那麼相同差值的情況下,我們從大到小迴圈,自然迴圈到後面的答案陣列字典序要比前面的小(因為我們選的target更小)。
第二步,再用兩個指標(pre_i=i-1,end_i=i+1)分別指向前面和後面的元素,我們需要改動陣列,讓target出現k次,那麼自然將target數字附件的數字變為target,差值會最小。又因為輸出答案字典序要小,那顯然優先變動值大的右邊。
k=k-arr[target] k為需要變動的次數
if end_i<10 and arr[end_i]:
if arr[end_i]<=k:
k=k-arr[end_i]
arr[target]+=arr[end_i]
arr[end_i]=0
cur_min+=arr[end_i]*(end_i-target)
else:
arr[target]+=k
cur_min+=k*(end_i-target)
k=0arr[end_i]-=k
if pre_i>0 and arr[pre_i]:
跟end_i差不多的處理
end_i+=1
pre_i-=1 #兩個指標一起挪動一格
if cur_min>min:#如果發現當前差值已經大於全域性差值,不需要再繼續,說明當前這個target是錯的
break
if k==0 and cur_min<=min:
min=cur_min
res_arr=arr
對於pre_i同理,先判斷end_i接著判斷pre_i,保證每次迴圈,end_i+=1和pre_i-=1同時,因為始終要找最近的元素。迴圈直到k=0,如果cur_min<=min,儲存新的差值以及arr陣列。因為我們所有的迴圈都從大到小,所以相同差值情況下,後更新的那個arr陣列永遠是字典序更小的。另外
(如果這題是787686,那應該先將8變為7:777686,而不是先變6:777787,這點我寫的時候沒考慮到,所以迴圈的時候從小到大,先變了6,也導致沒ac,後面交卷腦子清醒下來才發現,實在可惜。)
第三步:通過前面兩步我們已經得到結果差值和陣列,但我們得到的陣列arr並不是最終的數字串而是一格儲存了數字串中數字出現次數的陣列。例如我們最後得到的結果是arr[7]=5,arr[5]=1,arr[else]=0的陣列而不是777577。我們需要利用arr將原來的數字787585轉換成777577。
我們遍歷這個數字串,遇到乙個數字n,如果arr[n]=0,將這個數字轉成target,如果arr[n]>0,將arr[n]-=1。
arr[8]=0,arr[5]=1那麼遇到的8都會被轉為7,遇到的第乙個5讓arr[5]減一變為0,後面的5轉為7,轉換後的數字串就是777577。
總結下第三題的題解:
為了獲得arr陣列,我們需要遍歷一遍原字串o(n)
1:選定target,target只會從0到9,迴圈為10次,與原數字串的長度無關,o(1)的時間複雜度
2:對於每個target,經過第二步的處理,pre_i+end_i的迴圈次數顯然也是10次。
3:用得到的arr陣列將原數字串轉化為新的數字串o(n)
最終時間複雜度位o(n),本題難點因在於相同差值的情況下,如果確保答案字典序最小,當然我們可以把所有答案都儲存下來,輸出其中最小的那個,但顯然空間複雜度太高,而且我們得到的是arr陣列,還需要對每個答案進行轉化。所以我們利用target的選取從大到小以及數字轉變也優先轉變大的數字來確保後更新的arr字典序最小。
這題我只ac了15%,原因是我target的選取與數字的轉變(pre_i在end_i前面)都是從小到大,所以字典序反而最大,最簡單的例子就是787686,從小到大為787777(因為先轉pre_i,也就是6,轉完才去轉end_i)從大到小則是777677。
筆試的時候一定要冷靜,冷靜,冷靜。筆試題最不會特別難,如果冷靜下來考慮清楚邊界條件和一些約束條件,還是挺容易ac,我就是太慌了,導致沒思考清楚字典序和迴圈之間的對應關係。只要迴圈都改為從大到小,應該可以通過。
第四題:給乙個陣列n以及乙個k,最多可以移除k的元素,求給出陣列最大的連續子陣列長度。例如[1,1,1,2,1,3,3,4],k=2.答案是4
典型的dp題,這題leetcode上有簡單版,也就是k固定1或者2。美團筆試的第二題好像就是k=1的情況。
當時寫完第三題已經只有4分鐘了,來不及寫第四題,不過第一反應就知道是個dp題。之前遇到的都是k是固定的,所以這題一開始沒什麼思路。後面突然想到k固定的時候只是dp的陣列大小也固定了,那麼k其實影響的只是dp的陣列大小而已。
題解:dp的行數顯然是陣列長度n,那麼列數呢?哈哈,列數其實就是k+1。dp的核心思想不就是儲存之前的結果嗎,那麼我們可以移除k個元素,顯然會有k+1(0也是一條)條不同的結果。那麼列數為k+1是很自然的事情。下面上乙個**
arr=[1,2,2,1,1,2,2,4]
n=len(arr)
k=2res=0
dp=[1]*n
for i in range(n):
dp[i]=[1]*(k+1)
for i in range(1,n):
for t in range(k+1):
if i-t-1<0:
break
if arr[i]==arr[i-t-1]:
for q in range(t,k+1):
dp[i][q]=dp[i-t-1][q-t]+1
res=max(dp[i][q],res)
break
#print(dp)
print(res)
這題如果想通了dp的核心想法其實就不難。我們把每次迴圈都當做一次決策,當前決策是根據之前的決策與當前的元素來進行。例如原題目明顯可以通過遞推來解決,遞推顯然有前後關係,dp可以保留前一步的決策,並通過狀態轉移方程來生成當前的決策,如果k=0,那麼非常簡單,就是算陣列的最長連續陣列。dp陣列就是1*n,每次決策只需要轉移一種狀態,而如果k=1呢,那麼每次決策顯然有兩種狀態,一種k=0,也就是不需要轉移元素的情況,k=1,轉移一種元素的情況,dp陣列就是2*n,也很簡單,無非就是兩條狀態轉移方程。所以dp的陣列就是(k+1)*n,我們需要有k條狀態轉移方程。
那麼只需要明白狀態轉移方程怎麼寫就可以解決問題了。
以[1,2,2,1,1,2,2,4],k=2為例子。dp的結果為:
[[1, 1, 1], [1, 1, 1], [2, 2, 2], [1, 1, 2], [2, 2, 3], [1, 1, 3], [2, 2, 4], [1, 1, 1]]。
k=2,那麼i-1,i-2,i-3分別對應k=0,k=1,k=2的情況,判斷arr[i]和上面三個哪個相等,來找到i元素決策所需要的上一次決策資訊。
例如下標為5的時候,arr[5]=2,arr[4]=1,arr[3]=1,arr[2]=2,arr[5]==arr[2],那麼dp[5]的狀態就應該由dp[2]來更新,我們需要更新三種狀態,分別是k=0,1,2的情況,5和2之間相隔兩個元素,對應k=2的狀態,所以dp[5][2]=dp[2][2-2]+1。也就是dp[2]k=0對應dp[5]k=2。而dp[5]k=0,k=1(0-2,1-2)都不在範圍內,所以不更新,預設為1。
ok。四道題的題解都講完了,3,4題我都沒ac,第三題很可惜,**寫出來,但沒考慮字典序的問題,寫完因為沒什麼時間,腦子也有點亂,所以就沒繼續改,而是看第四題去了,想起來還是有點後悔。
2023年3月vivo春招 筆試
1 在vivo生產線上,每位職工隨著對手機加工流程認識的熟悉和經驗的增加,日產量也會不斷飆公升。假設第一天量產1臺,接下來2天 即第 二 三天 每天量產2件,接下來三天 即第 三 四 五天 每天量產3件。以此類推,計算出第n天總共可以量產的手機數量。2 現給定任意正整數n,請尋找並輸出最小的正整數m...
2023年春4月月賽題解
問題a include include using namespace std int m,n const int n 1010 int dp n n intmain cout dp m n endl return0 問題b include include include using namespa...
廈門飛魚科技 2020春招實習
體感做過最難的筆試,題量大的誇張,兩個半小時,我記得要做選擇 程式填空 簡答 5道程式設計選3 英文題目 加分題 來不及做,題目都沒看,應該是手撕類的 萬惡的智力測試題 都是些圖形,數字找規律的題,做完感覺自己像個弱智,而且我記得限時半小時內做完二十題還是三十題 當時做完挺受打擊的,程式設計題我預留...