前言
這周很忙,但是越忙的時(shí)候反而越喜歡抽空做算法題。
歡迎關(guān)注algorithm文集。
這次A、B、C都是很合適的面試題。
正文
A. Memory and Crow
題目鏈接
題目大意:
給出n個(gè)數(shù)字。(a[1],?a[2],?...,?a[n])
a[i]和b[i]的關(guān)系如下。
a[i]?=?b[i]?-?b[i+1]?+?b[i+2]?-?b[i+3]....
給出數(shù)組a[i],求數(shù)組b[i]。
n (2?≤?n?≤?100?000)
a[i] (?-?1e9?≤?a[i]?≤?1e9)
** Examples**
** input**
5
6 -4 8 -2 3
** output**
2 4 6 1 3
** input**
5
3 -2 -1 5 6
output
1 -3 4 11 6
題目解析:
根據(jù)通項(xiàng)公式,知道b[n] = a[n];(因?yàn)椴荒艽嬖赽[n+1])
然后倒著求b[i], b[i] = a[i] + a[i+1];
B. Memory and Trident
題目鏈接
** 題目大意:**
輸入一個(gè)字符串s,由 'L', 'R', 'U', or 'D'組成,分別表示點(diǎn)P在原點(diǎn)的向左、右、上、下前進(jìn)一步。
修改字符串的序列,每次操作能修改一個(gè)字符為其他字符(L/R/U/D),問點(diǎn)P按照字符串s移動(dòng)后能回到原點(diǎn)的最小操作次數(shù);
如果可以,輸出做小操作次數(shù);
如果不能,則輸出-1;
** Examples**
** input**
RRU
** output**
-1
** input**
UDUR
** output**
1
** 題目解析:**
先考慮不能情況。
如果字符串的長度為奇數(shù),那么必然不能回到原點(diǎn)。
如果字符串的長度為偶數(shù),那么必然有解。(最多把所有的字符串變成UDUD)
然后分開考慮,L 和 R 相對(duì), U 和 D 相對(duì)。
求出在x方向和y方向的需要修改的字符數(shù)量。
容易知道我們可以把需要修改的數(shù)量加起來,然后除以2可以得到修改的次數(shù)。(兩個(gè)方向的需要修改數(shù)量,必然為偶數(shù))
C. Memory and De-Evolution
題目鏈接
題目大意:
有兩個(gè)正三角形,邊長分別為x,y。
現(xiàn)在可以對(duì)三角形進(jìn)行操作,每次操作可以改變?nèi)切蔚囊粭l邊長度(為整數(shù)),變成另外一個(gè)三角形。
問讓正三角形x 變成 正三角形y 的最小操作次數(shù)。
x and y (3?≤?y?<?x?≤?100?000)
** Examples**
** input**
6 3
** output**
4
樣例解釋:666 -> 663 -> 643 -> 343 -> 333 總共需要操作4次
** 題目解析:**
三角形的性質(zhì):兩邊之和大于第三邊。
反過來考慮,把三角形y變成三角形x。(操作步數(shù)是一致的)
那么自然可以想到一種貪心:每次把最小的邊變得最大。
每次操作完排序,再對(duì)最小的進(jìn)行變大。
直到最小的邊也等于x。
D. Memory and Scores
題目鏈接
** 題目大意:**
A 和 B玩一個(gè)游戲,游戲分成t輪。
初始時(shí),A和B的分?jǐn)?shù)為a和b;
每輪游戲,A和B都可以從[-k, k]的區(qū)間里面選擇一個(gè)整數(shù)加到自己的分?jǐn)?shù);
問最后有多少種可能,A的分?jǐn)?shù)大于B的分?jǐn)?shù)。
(只要某一輪A或者B的分?jǐn)?shù)不同,即視為不同的可能)
a, b, k, and t (1?≤?a,?b?≤?100, 1?≤?k?≤?1000, 1?≤?t?≤?100)
結(jié)果mod 1?000?000?007 (1e9?+?7)。
Example
** input**
1 2 2 1
** output**
6
** 樣例解釋:**
In the first sample test, A starts with 1 and B starts with 2. If B picks ?-?2, A can pick 0, 1, or 2 to win. If B picks ?-?1, A can pick 1 or 2 to win. If B picks 0, A can pick 2 to win. If B picks 1 or 2, A cannot win. Thus, there are 3?+?2?+?1?=?6 possible games in which A wins.
** 題目解析:**
容易知道,每次的選擇都是[-k, k],那么總共就有(2k + 1)個(gè)選擇;
t輪之后就是(2k+1)^t個(gè)選擇。
接下來考慮去重,存在一輪分?jǐn)?shù)不同,即是在第i輪的時(shí)候,選擇不同的數(shù)字。
那么,我們用dp[i][j]來表示 前i輪,分?jǐn)?shù)等于j的選擇個(gè)數(shù)。
這樣就可以統(tǒng)計(jì)出t輪之后,分?jǐn)?shù)為j的不同選擇個(gè)數(shù)。
先是對(duì)A dp出t次后的結(jié)果,再對(duì)B dp出t次后的結(jié)果。這兩個(gè)都是O(NK^2)。
最后再對(duì)dpB[n][j] 統(tǒng)計(jì)下所有∑dpA[n][c],c > j,然后相乘,得到B為j的時(shí)候,A贏的選擇數(shù)。
最后累加j = [-k * k / 2, k * k / 2]的和即可。
** 小技巧:**
1、為了方便計(jì)算,把所有的狀態(tài)都加上一個(gè)offset,這樣-k*k/2 就變成正數(shù),避免dp過程中訪問到下標(biāo)是負(fù)的情況;
2、為了狀態(tài)轉(zhuǎn)移更快,dpA[i][j] 可以存分?jǐn)?shù)為1到j(luò)的和,這樣分?jǐn)?shù)為j的值可以通過dpA[i][j] - dpA[i][j - 1]求出。
總結(jié)
趁著寫文章,回顧下這四個(gè)題目,發(fā)現(xiàn)A/B/C對(duì)于我來說都是很簡單題目,D需要一些思考和細(xì)節(jié)的考慮,算中等題。
但是對(duì)某些牛,可能他做D的難度就和我做前三個(gè)的難度差不多。
差距是哪里??
1、角度,大牛思考更全面,能用最適當(dāng)?shù)乃悸啡ソ鉀Q問題;
2、熟練度,像offset、mod、累加這些trick大牛一眼就看穿并且熟練地實(shí)現(xiàn);
3、復(fù)雜度,大牛經(jīng)常面對(duì)很多更復(fù)雜的情況,再回過來處理這些題目就更為容易;
或許還有其他原因,但是就這三點(diǎn)就值得深思。
如果是要做題目,應(yīng)該先看到出題人的思路,順著這個(gè)方向查看設(shè)置的trick,在有具體的解法后要完善好細(xì)節(jié)再實(shí)現(xiàn);
如果是工作開發(fā),則是要理解產(chǎn)品的需求,從用戶的角度觀察未來可能的變化,在設(shè)計(jì)好具體的解決方案后,再進(jìn)行開發(fā);
三思而后行,這是非常難以堅(jiān)持的要求。