解析:
1.解題思路
對(duì)于輸入的字符串s,分別找出長(zhǎng)度為2和3的最小子串。子串必須是連續(xù)的,需要遍歷所有可能的連續(xù)子串,然后比較它們的字典序。
對(duì)于長(zhǎng)度為2的情況,假設(shè)字符串長(zhǎng)度是n,那么可能的子串有n-1個(gè)。每個(gè)子串是s[i]和s[i+1]。我需要比較所有這些子串,找到字典序最小的一個(gè)。同樣,長(zhǎng)度為3的話,子串有n-2個(gè),每個(gè)是s[i],s[i+1],s[i+2]。
在C++中,如何生成子串?使用substr函數(shù),第一個(gè)參數(shù)是起始位置,第二個(gè)參數(shù)是長(zhǎng)度。例如,s.substr(i, 2)就是取從i開始的2個(gè)字符的子串。
當(dāng)n是1e5的時(shí)候,每次substr都要復(fù)制字符,對(duì)于長(zhǎng)度為2的子串,復(fù)制兩個(gè)字符,對(duì)于長(zhǎng)度為3的復(fù)制三個(gè)。循環(huán)次數(shù)是O(n),所以總的時(shí)間復(fù)雜度是O(n) * O(k),其中k是子串的長(zhǎng)度。對(duì)于k=2或3來(lái)說(shuō),這應(yīng)該還是可以接受的,因?yàn)榭偟臅r(shí)間是O(n*2 + n*3) = O(n),對(duì)于n=1e5來(lái)說(shuō),是可以的。
但是,有沒有可能優(yōu)化?比如,不生成子串,而是直接比較字符?
對(duì)于長(zhǎng)度為2的最小值,記錄其起始位置i,在每次比較時(shí),比較當(dāng)前i的兩個(gè)字符和當(dāng)前最小值的兩個(gè)字符。
或者,維護(hù)一個(gè)當(dāng)前最小的兩個(gè)字符,比如char a和char b,初始為'z'和'z'。每次比較s[i]和s[i+1]與當(dāng)前的a和b:
如果s[i] < a,那么無(wú)論第二個(gè)字符如何,當(dāng)前子串更小?;蛘?,當(dāng)s[i] == a,但s[i+1] < b,則更小。
這樣,可以避免構(gòu)造子串,直接比較字符。
例如:
處理長(zhǎng)度為2的子串:
初始化min2的兩個(gè)字符為'z'和'z'。
for (int i=0; i<=n-2; ++i) {
char c1 = s[i], c2 = s[i+1];
if (c1 < min_c1 || (c1 == min_c1 && c2 < min_c2)) {
min_c1 = c1;
min_c2 = c2;
然后,將min_c1和min_c2組合成字符串輸出。
字符串長(zhǎng)度為3 的也是同理。
考點(diǎn)
字符串處理:
如何高效地遍歷和處理字符串?dāng)?shù)據(jù)。
提取子串的操作。
字典序比較:
理解字典序的概念,并能夠進(jìn)行字符串之間的字典序比較。
邊界條件處理:
處理字符串長(zhǎng)度不足2或3的情況(但題目已保證字符串長(zhǎng)度至少為3,所以這里主要是考慮代碼健壯性)。
效率優(yōu)化:
由于字符串長(zhǎng)度可能達(dá)到10^5,需要確保算法的時(shí)間復(fù)雜度是線性的或接近線性的,以避免超時(shí)。
2. 解題思路
首先通過數(shù)據(jù)范圍可以看到n,m的值為1e9,如果通過遍歷每個(gè)點(diǎn)來(lái)求邊數(shù),那么肯定會(huì)超時(shí),只能得到n,m≤100 這部分的分值。如果想通過就必須用數(shù)學(xué)方法或者公式來(lái)處理。
1. 先看點(diǎn)數(shù)。原來(lái)的總點(diǎn)數(shù)是n*m,然后減去障礙的數(shù)量k。,所以點(diǎn)數(shù)應(yīng)該是n*m - k。
2. 接下來(lái)是邊數(shù)的問題。每個(gè)邊是否存在的條件是兩個(gè)相鄰的點(diǎn)都存在。所以需要計(jì)算所有可能的相鄰邊,然后減去那些因?yàn)橹辽僖粋€(gè)點(diǎn)是障礙物而無(wú)法存在的邊。在網(wǎng)格圖中,橫向的邊數(shù)目是n*(m-1),每行有m-1條橫向邊,總共n行??v向邊數(shù)目是m*(n-1)條。總的邊數(shù)是n*(m-1) + m*(n-1)。
3. 現(xiàn)在的問題是計(jì)算這些被障礙物影響的邊數(shù)目。每個(gè)障礙物會(huì)影響四個(gè)方向的邊:上、下、左、右。如果一個(gè)障礙物的周圍點(diǎn)也是障礙物,或者越界,對(duì)應(yīng)的邊本來(lái)就不存在,因此要逐個(gè)障礙物檢查周圍的四個(gè)方向是否存在可能的邊,并統(tǒng)計(jì)這些邊是否被移除
(1) 統(tǒng)計(jì)所有水平邊中被阻擋的數(shù)目:即對(duì)于每個(gè)水平邊(i,j)-(i,j+1),如果至少有一個(gè)端點(diǎn)被阻擋,則這條邊不存在。同樣處理垂直邊。
(2) 同樣的,對(duì)于垂直邊(i,j)-(i+1,j),如果至少有一個(gè)端點(diǎn)被阻擋,則這條邊不存在
另外,由于障礙數(shù)量相對(duì)較少,我們可以通過哈希表(或數(shù)組,如果障礙坐標(biāo)范圍有限)來(lái)快速判斷一個(gè)位置是否為障礙。
考點(diǎn)
數(shù)學(xué)計(jì)算:
如何通過數(shù)學(xué)公式計(jì)算出網(wǎng)格圖上的總點(diǎn)數(shù)和總邊數(shù)。
如何根據(jù)障礙的位置調(diào)整點(diǎn)數(shù)和邊數(shù)。
數(shù)據(jù)范圍處理:
如何處理大數(shù)據(jù)范圍(如n和m達(dá)到10^9)下的計(jì)算問題。
如何高效地存儲(chǔ)和處理障礙位置信息。
邊界條件處理:
當(dāng)網(wǎng)格圖上沒有障礙時(shí)(k=0)的特殊情況處理。
當(dāng)障礙數(shù)量很多時(shí),如何避免重復(fù)減少同一條邊。
算法效率:
如何確保算法的時(shí)間復(fù)雜度足夠低,以處理大數(shù)據(jù)量的輸入。
3.解題思路
這個(gè)問題是一個(gè)典型的0/1背包問題的變種,我們需要在滿足容量限制的情況下,最大化去兩個(gè)地點(diǎn)的人數(shù)之和。我們需要對(duì)每個(gè)班級(jí)做出決策,使其去第一個(gè)地點(diǎn)或第二個(gè)地點(diǎn),以最大化滿足學(xué)生意愿的總?cè)藬?shù)。
具體步驟如下:
定義狀態(tài):
使用動(dòng)態(tài)規(guī)劃數(shù)組 dp[i][j][k] 表示前 i 個(gè)班級(jí)中,第一個(gè)地點(diǎn)安排了 j 人,第二個(gè)地點(diǎn)安排了 k 人時(shí),能滿足的最大意愿人數(shù)。
但由于三維數(shù)組空間復(fù)雜度較高,可以優(yōu)化為二維數(shù)組 dp[j][k],其中 j 和 k 分別表示兩個(gè)地點(diǎn)的當(dāng)前人數(shù)。
狀態(tài)轉(zhuǎn)移:
對(duì)于每個(gè)班級(jí),有兩種選擇:去第一個(gè)地點(diǎn)或第二個(gè)地點(diǎn)。
如果第 i 個(gè)班級(jí)去第一個(gè)地點(diǎn),則 dp[j + a[i]][k] = max(dp[j + a[i]][k], dp[j][k] + a[i])
如果第 i 個(gè)班級(jí)去第二個(gè)地點(diǎn),則 dp[j][k + b[i]] = max(dp[j][k + b[i]], dp[j][k] + b[i])
初始化:
dp[0][0] = 0,表示沒有班級(jí)安排時(shí),滿足人數(shù)為0。
結(jié)果查找:
遍歷 dp[A][B] 及其附近的值,找到最大的滿足人數(shù)。
記錄路徑,即每個(gè)班級(jí)的選擇。
處理無(wú)解情況:
如果最終找到的最大值小于等于初始值(即沒有任何班級(jí)被安排),則輸出 -1 和 error。
考點(diǎn):
動(dòng)態(tài)規(guī)劃:掌握如何根據(jù)子問題構(gòu)建動(dòng)態(tài)規(guī)劃數(shù)組以及狀態(tài)轉(zhuǎn)移方程。
背包問題變種:理解0/1背包問題的變種,如何在有限資源下最大化某種指標(biāo)。
邊界條件處理:如何判斷是否存在合法解。
狀態(tài)記錄與回溯:在動(dòng)態(tài)規(guī)劃中找到最優(yōu)解后,如何回溯得到具體的方案。
4.解題思路
這個(gè)問題可以看作是一個(gè)動(dòng)態(tài)規(guī)劃或前綴和與哈希表結(jié)合的問題,關(guān)鍵在于如何高效地判斷一個(gè)連續(xù)子數(shù)組的和是否是某個(gè)給定數(shù) p 的倍數(shù)。
方法一:動(dòng)態(tài)規(guī)劃(可能超時(shí),適用于小規(guī)模數(shù)據(jù))
我們可以使用一個(gè)二維動(dòng)態(tài)規(guī)劃數(shù)組 dp[i][j],其中 i 表示考慮到第 i 個(gè)糖果,j 表示當(dāng)前糖果分配后,剩余糖果甜蜜度之和模 p 的結(jié)果。狀態(tài)轉(zhuǎn)移方程可能比較復(fù)雜,而且這種方法的空間復(fù)雜度和時(shí)間復(fù)雜度都可能很高,不適合大規(guī)模數(shù)據(jù)。
方法二:前綴和與哈希表(更高效)
計(jì)算前綴和:
首先,我們計(jì)算糖果甜蜜度的前綴和數(shù)組 prefix_sum,其中 prefix_sum[i] 表示前 i 個(gè)糖果的甜蜜度之和。
使用哈希表記錄余數(shù)出現(xiàn)的位置:我們遍歷前綴和數(shù)組,并計(jì)算每個(gè)前綴和模 p 的余數(shù)。我們使用一個(gè)哈希表 remainder_map 來(lái)記錄每個(gè)余數(shù)第一次出現(xiàn)的位置。
判斷連續(xù)子數(shù)組的和是否為 p 的倍數(shù):對(duì)于每個(gè)位置 i,我們檢查 prefix_sum[i] % p 的相反數(shù)(即 (p - prefix_sum[i] % p) % p,這里取模是為了處理負(fù)數(shù)情況)是否在哈希表中出現(xiàn)過。如果出現(xiàn)過,說(shuō)明存在一個(gè)之前的位置 j(j < i),使得 prefix_sum[i] - prefix_sum[j] 是 p 的倍數(shù),即 a[j+1] + a[j+2] + ... + a[i] 是 p 的倍數(shù)。
更新最大小朋友數(shù)量:我們維護(hù)一個(gè)變量來(lái)記錄最多能有多少位小朋友高興,每次找到一個(gè)符合條件的連續(xù)子數(shù)組時(shí),就嘗試更新這個(gè)變量。
考點(diǎn)
前綴和與哈希表的應(yīng)用:如何結(jié)合前綴和與哈希表來(lái)高效地解決問題。
模運(yùn)算的性質(zhì):如何處理模運(yùn)算,特別是處理負(fù)數(shù)取模的情況。
數(shù)據(jù)結(jié)構(gòu)的選擇:在大數(shù)據(jù)量情況下,如何選擇合適的數(shù)據(jù)結(jié)構(gòu)來(lái)存儲(chǔ)和查詢信息。
多組數(shù)據(jù)的處理:如何編寫能夠處理多組數(shù)據(jù)的代碼。
5.解題思路
這個(gè)問題要求我們?cè)谝粋€(gè)環(huán)形數(shù)組上進(jìn)行切割,使得切割后的每段子數(shù)組的和的最大公約數(shù)最大化,并且需要對(duì)每個(gè)可能的切割段數(shù) k(從1到 n)都求出這個(gè)最大化的最大公約數(shù)。
由于數(shù)組是環(huán)形的,我們可以將其復(fù)制一遍接在后面,這樣在處理邊界情況時(shí)就可以簡(jiǎn)單地看作是在一個(gè)線性數(shù)組上進(jìn)行切割,而不需要考慮環(huán)形的問題。
暴力求解思路:
對(duì)于每個(gè)可能的分段數(shù)k,枚舉所有可能的分段方式。
計(jì)算每段的和,然后求這些和的最大公約數(shù)。
更新最大公約數(shù)的最大值。
這種方法的時(shí)間復(fù)雜度是指數(shù)級(jí)的,因?yàn)閷?duì)于每個(gè)k,都有大量的分段方式需要枚舉,不適合處理大規(guī)模數(shù)據(jù)。
優(yōu)化思路:
觀察到最大公約數(shù)具有性質(zhì):如果兩個(gè)數(shù)a和b的最大公約數(shù)是g,那么對(duì)于a和b的任意倍數(shù)ma和mb,它們的最大公約數(shù)仍然是g的倍數(shù)(或g本身)。
因此,我們不需要枚舉所有可能的分段方式,而是可以枚舉所有可能的和(或和的倍數(shù)),然后求這些和的最大公約數(shù)。
可以使用前綴和數(shù)組來(lái)快速計(jì)算任意區(qū)間的和。
然后,利用輾轉(zhuǎn)相除法(歐幾里得算法)來(lái)求這些和的最大公約數(shù)。
實(shí)現(xiàn)步驟:
計(jì)算數(shù)組的前綴和。
對(duì)于每個(gè)可能的分段數(shù)k,枚舉所有可能的起點(diǎn),然后計(jì)算每段(長(zhǎng)度為n/k,向上取整或根據(jù)余數(shù)調(diào)整)的和。
使用歐幾里得算法求這些和的最大公約數(shù)。
考點(diǎn)
前綴和數(shù)組:
用來(lái)快速計(jì)算任意區(qū)間的和。
這是一個(gè)常用的數(shù)組處理技巧,特別是在需要頻繁計(jì)算區(qū)間和時(shí)。
歐幾里得算法:
用來(lái)求兩個(gè)數(shù)的最大公約數(shù)。
這是數(shù)論中的基礎(chǔ)知識(shí),也是算法競(jìng)賽中常用的技巧。
時(shí)間復(fù)雜度優(yōu)化:
如何在保證正確性的前提下,盡可能減少算法的時(shí)間復(fù)雜度。
這需要對(duì)問題進(jìn)行深入的分析,并找到問題的本質(zhì)特征,從而設(shè)計(jì)出更高效的算法。
數(shù)組處理:
如何高效地處理數(shù)組數(shù)據(jù),包括數(shù)組的遍歷、修改和查詢等。
這是編程中的基本技能,也是解決很多問題的關(guān)鍵。
數(shù)論知識(shí):
最大公約數(shù)、最小公倍數(shù)等數(shù)論基礎(chǔ)知識(shí)。
這些知識(shí)在算法競(jìng)賽中經(jīng)常出現(xiàn),需要熟練掌握。
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.