程序員進(jìn)階之算法練習(xí)(二十三)

前言

7月,忙著學(xué)習(xí)ReactNative相關(guān),這部分后續(xù)再詳細(xì)介紹,先抽點(diǎn)時(shí)間補(bǔ)上算法文集的更新。

正文

1、Tennis Championship

題目鏈接
** 題目大意:**
n個(gè)人參加若干個(gè)比賽,比賽是1v1,輸?shù)娜瞬荒茉賲⒓颖荣悺?br> 如果一個(gè)人贏了k次,那么他只會(huì)與贏次數(shù)不小于k-1次的人比賽;
問(wèn),贏得最多的那個(gè)人,能贏多少次;
(n<=1e18)

** Example**
** input**
4
output
2
樣例解釋:四個(gè)人假設(shè)是ABCD,那么可以(A, B),(C,D)分配,A和C贏了;再分配(A,C),A贏了,共2次。

題目解析:
如果n個(gè)人,直接兩兩匹配,贏的人再兩兩匹配,這樣會(huì)浪費(fèi)一部分人,因?yàn)橼Ak次的人是可以和k-1次的比賽;
那么,保證每場(chǎng)比賽都是贏k次和k-1次的人,即可滿足最優(yōu)解;(注意,贏0次只能贏0次比)

那么k=1的時(shí)候,sum1=2;
k=2, sum2=2+1=3;
k=3, sum3=sum2+sum1=5;
k=4, sum4=sum3+sum2=8;
k=5, sum5=sum4+sum3=13;
...
sum[i] 表示一個(gè)人贏k次,需要sum[i]個(gè)人參與;
以此類推,可以得到最大的k值。

2、Taxes

題目鏈接
** 題目大意:**
給出一個(gè)整數(shù)n(n<=2e9);
現(xiàn)在把n分成k個(gè)數(shù)的和,假設(shè)是a[i],那么有:
a[1]+a[2]+a[3]...=n;(要求a[i]>=2, k>=1)
分出數(shù)字a[i]的cost,為a[i]的最大因子;(除去a[i])
分成k個(gè)數(shù)的代價(jià)為k個(gè)數(shù)字的cost和;

給出n,求分成若干個(gè)數(shù)字的最小cost。

** Examples**
** input**
4
** output**
2
樣例解釋:4=2+2,2的代價(jià)是1,于是 cost=1+1=2

** 題目解析:**
分出數(shù)字a[i]的cost為a[i]的最大因子,那么分出素?cái)?shù)的cost為1;
哥德巴赫猜想可以知道:
1、任一大于2的偶數(shù),都可表示成兩個(gè)素?cái)?shù)之和;
2、任一大于5的整數(shù)都可寫成三個(gè)質(zhì)數(shù)之和。

于是有:
素?cái)?shù)是1;
偶數(shù)是2;
如果是奇數(shù), 那么最大為3;
還有一種情況是奇數(shù)=2+素?cái)?shù),因?yàn)?也算素?cái)?shù),如果能拆出這種答案為2。

可怕的隊(duì)友提供的想法,下面是他短小精悍的代碼:

int isprime (int n) {
    for (int i = 2; i * i <= n; ++ i)if (n%i==0) return false;
    return true;
}
int main (){
    int n; cin >> n;
    int ans = 0;
    if (isprime(n)) ans = 1;
    else if(n%2==0) ans = 2;
    else {
        if(isprime(n-2)) ans = 2;
        else ans = 3;
    }
    cout<<ans<<endl;
    return 0;
}

3、Sea Battle

題目鏈接
** 題目大意:**
n個(gè)格子排成一行,b個(gè)連續(xù)的格子可以放下一艘ship,總共有a艘ship;
ships可以相鄰,但是不能多個(gè)ship覆蓋同個(gè)格子;
現(xiàn)在朝這n個(gè)格子開(kāi)槍,目前已經(jīng)打了k槍,但是沒(méi)有打中一艘ship;
現(xiàn)在問(wèn),還需要打多少槍,保證至少能打中一艘ship。
n, a, b, k (1?≤?n?≤?2e5, 1?≤?a,?b?≤?n, 0?≤?k?≤?n?-?1)

** Examples**
** input**
5 1 2 1
00100
output
2
4 2
樣例解釋:
5 1 2 1 分別對(duì)應(yīng)n、a、b、k;
00100 表示第3個(gè)格子已經(jīng)開(kāi)槍打過(guò);(題目保證1的數(shù)量等于k)

題目解析:
貪心。
從左到右,只要出現(xiàn)連續(xù)的b個(gè)空的格子就打一槍,假設(shè)總共打了m槍;
最后因?yàn)橛衋艘船,答案就是m-a+1;(假設(shè)有3個(gè)位置,2艘船,那么只要打兩槍即可)

4、Anton and Tree

題目鏈接
** 題目大意:**
n個(gè)點(diǎn)的樹(shù),樹(shù)的節(jié)點(diǎn)有兩種黑色(黑、白),有兩個(gè)操作:
1、path(u, v):表示u到v的最短路徑,包括u、v;
2、paint(v):u是樹(shù)上任意點(diǎn),假如path(u, v)上所有節(jié)點(diǎn)的顏色相同,那么u的顏色會(huì)change(黑白互換);

如圖,給出一棵樹(shù):



對(duì)節(jié)點(diǎn)3進(jìn)行paint操作之后:


現(xiàn)在給出一棵樹(shù)和節(jié)點(diǎn)顏色,求最少需要幾次paint操作,使得樹(shù)上所有的節(jié)點(diǎn)顏色相同。
n (1?≤?n?≤?200?000)

Examples
input
11
0 0 0 1 1 0 1 0 0 1 1
1 2
1 3
2 4
2 5
5 6
5 7
3 8
3 9
3 10
9 11
** output**
2

** 題目解析:**
相同的顏色縮點(diǎn),得到一個(gè)黑白交替的樹(shù)。
要使得整棵樹(shù)的節(jié)點(diǎn)顏色變成相同,可以找到最長(zhǎng)的鏈,然后對(duì)著鏈的中間節(jié)點(diǎn)k,不斷進(jìn)行paint(k)操作即可。
答案為最長(zhǎng)鏈的長(zhǎng)度/2。

要點(diǎn):并查集縮點(diǎn)+dfs找最長(zhǎng)鏈。

總結(jié)

第1題其實(shí)是斐波那契數(shù)列,但是用題意很好的包裝起來(lái);
第3題是典型的貪心題目,但是增加了a艘ship的變量,對(duì)思考造成一定的影響;
1、3都很適合作為面試的題目,2、4對(duì)一個(gè)未接觸過(guò)該方面知識(shí)的人來(lái)說(shuō)不可解。
代碼都可以在github可以找到。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容