牛客面試題 紅和綠(字首和優化)
阿新 • • 發佈:2018-12-20
連結:https://www.nowcoder.com/questionTerminal/56ab932abac44c8aabf0af75f598a0b4 來源:牛客網 牛牛有一些排成一行的正方形。每個正方形已經被染成紅色或者綠色。牛牛現在可以選擇任意一個正方形然後用這兩種顏色的任意一種進行染色,這個正方形的顏色將會被覆蓋。牛牛的目標是在完成染色之後,每個紅色R都比每個綠色G距離最左側近。牛牛想知道他最少需要塗染幾個正方形。 如樣例所示: s = RGRGR 我們塗染之後變成RRRGG滿足要求了,塗染的個數為2,沒有比這個更好的塗染方案。
輸入描述:輸入包括一個字串s,字串s長度length(1 ≤ length ≤ 50),其中只包括'R'或者'G',分別表示紅色和綠色。
輸出描述:輸出一個整數,表示牛牛最少需要塗染的正方形數量
示例1
輸入 RGRGR
輸出 2
剛看到這個題的時候覺得就是想的模擬,把所有的R放在最右邊,所有的G房子最左邊,並且我感覺題還誤導了,如樣例所示: s = RGRGR 我們塗染之後變成RRRGG滿足要求了,塗染的個數為2,沒有比這個更好的塗染方案。
但其實他還可以直接全塗成R 或 G的情況,只要塗得次數最少即可,比如 GGGGRRR 輸出應該為 GGGGGGG
網上的好多部落格都沒說這一點
明白了這點就好做了,直接掃每一位的左邊G的個數與R的個數取最小即可
#include<cstdio> #include<cstring> #include<string.h> #include<algorithm> #include<iostream> #include<stdlib.h> using namespace std; const int inf=0x3f3f3f3f; const int maxn=1000000; int main(){ char s[100]; scanf("%s",s); int minn=inf; int n=strlen(s); for(int i=0;i<n;i++){ int cnt=0; for(int j=0;j<i;j++){ if(s[j]!='R') cnt++; } for(int j=i;j<n;j++) { if(s[j]!='G') cnt++; } minn=min(minn,cnt); } printf("%d\n",minn); }
但是看題解的時候看見一大佬寫的字首和優化,直接變成O(1)的演算法
大佬的寫法:
for (int i = 1; i <= n; i++)
G[i] = G[i - 1] + (str[i - 1] == 'G');
for (int i = n; i > 0; i--)
R[i] = R[i + 1] + (str[i - 1] == 'R');
int ans = n;
for (int i = 0; i <= n; i++)
ans = min(ans, G[i] + R[i + 1]);
字首和就是把從(i,j)間的數的和求出來存起來 然後每次用的時候 比如求 (3-6)的區間和 直接用 sum(6)-sum(3)即可,O(1)複雜度。而這道題優化也就是在求左邊G和右邊R的時候用到了該思想。