來自:2017
年網易春招筆試題三
在幼兒園有
n個小朋友排列為乙個隊伍,從左到右乙個挨著乙個編號為(
0~n-1
)。其中有一些是男生,有一些是女生,男生用『
b』表示,女生用『
g』表示。小朋友們都很頑皮,當乙個男生挨著的是女生的時候就會發生矛盾。作為幼兒園的老師,你需要讓男生挨著女生或者女生挨著男生的情況最少。你只能在原隊形上進行調整,每次調整只能讓相鄰的兩個小朋友交換位置,現在需要盡快完成隊伍調整,你需要計算出最少需要調整多少次可以讓上述情況最少。
例如:ggbbg-->ggbgb-->gggbb
這樣就使之前的兩處男女相鄰變為一處相鄰,需要調整隊形2次。
輸入描述:
輸入資料報括乙個長度為
n且只包含g和
b的字串。
n不超過50。
輸出描述:
輸出乙個整數,表示最少需要的調整隊伍的次數。
輸入例子1:
ggbbg
輸出例子1:
2分析:
要使男生挨著女生或者女生挨著男生的情況最少,則調整後的隊形只存在
gg…gb..bb
和bb…bg…ggg
兩種情況,即,問題變成將原字串變為上述兩種情況中移動次數最少的那一種情況。
先寫出函式原型:
int mincount(constchar *p);
輸入為乙個字串,輸出為乙個整數。
每次只能交換相鄰的兩個元素,考慮其中一種情況
gg…gb…bb:
1、從左到右遍歷,當遇到
g時不變,判斷已出現
g的個數,若等於
g的總數則退出迴圈; 2
、當遇到
b時,看下乙個元素是否為
g,是的話交換兩個位置,遍歷下標加一,交換次數加一,判斷已出現
g的個數,若等於
g的總數則退出迴圈; 3
、下乙個元素是
b時,繼續判斷下個元素是否為
b,否則直到下個元素是g,將
g一步一步左移交換位置,判斷已出現
g的個數,若等於
g的總數則退出迴圈; 4
、再重複上述步驟直到退出迴圈。
最後返回兩種情況的次數,將最小值作為最終的結果。
下面給出**(
c++):
#include
using namespace std;
#define max 50
// 函式返回最終結果
int mincount(const char* p);
// 輸入字串並按照字元先後標準排序,返回次數
int sort(char*p,int len,char,char);
// 交換函式
void swap(char &,char &);
int main()
int mincount(const char* p)
// 判斷是否有非法字元
for(i = 0; i < len; i++) }
strcpy(tmp,p);
//兩種方式的排序所需的次數
m1 = sort(tmp,len,'g','b');
cout << "method1 : " << m1 << endl;
strcpy(tmp,p);
m2 = sort(tmp,len,'b','g');
cout << "method2 : " << m2 << endl;
return min(m1,m2);
}int sort(char*p,int len,char a,char b)
// 1、從左到右遍歷
for(i = 0; i < len; i++)
// 2、當遇到b時
else
// 出現a,次數再+1
tmpnum++;
// 每次交換兩個位置,交換次數加一
while(j > i)
// 4、判斷已出現a的個數,若等於a的總數則退出迴圈
if(tmpnum == numa)
break;
} }return ncount;
}
執行結果,當輸入為
ggbbg時:
當輸入為
gbbgbggbbb時:
進一步討論,題目需要將乙個字串按照類別分成兩堆(可以看成簡化的三色旗問題),
若已知排序後的結果,只需判斷某個字元在向目的方向移動時,中間有幾個其他字元,就可以知道該字元所需移動次數,最後計算每個字元需要的移動次數的總和,結果就為總共所需要的交換次數。
下面給出**(
c++):
#include
using namespace std;
#define max 50
int func(const char *p)
// 判斷是否有非法字元
for(i = 0; i < len; i++) }
for(i = 0; i < len; i++)
}m1 += tmp;
tmp = 0;
} }tmp = 0;
for(i = 0; i < len; i++)
}m2 += tmp;
tmp = 0;
} }cout << "method1 : " << m1 << endl;
cout << "method2 : " << m2 << endl;
return min(m1,m2);
}int main()
下面是輸出結果:
總結,本題應該不是主要考慮排序演算法,由於題目所給總數不超過
50,也不需要過分強調演算法複雜度,所得的結果只要避免男男交換或**交換即可。為避免需要比較兩種順序的結果大小,提高速度,應該可預先判斷怎樣排序是最優的,如判斷中點兩邊b和
g的數量,若左邊
b的數量大於右邊,則可近似認為
b排在左邊比排在右邊會交換更少的次數,這樣就可以只考慮
b排在左邊的情況,也符合實際情況,當然是否一定正確需要嚴格證明。
網易2017演算法題 調整隊形
題目是這樣的 在幼兒園有n個小朋友排列為乙個隊伍,從左到右乙個挨著乙個編號為 0 n 1 其中有一些是男生,有一些是女生,男生用 b 表示,女生用 g 表示。小朋友們都很頑皮,當乙個男生挨著的是女生的時候就會發生矛盾。作為幼兒園的老師,你需要讓男生挨著女生或者女生挨著男生的情況最少。你只能在原隊形上...
調整隊形 TJOI2007
給定乙個初始的序列以及四種操作,問最少操作多少次可以是序列變為回文序列。操作如下 在隊伍左側或右側新增乙個數 在隊伍中插入乙個數 刪除乙個數 改變乙個數的值 看到給定的序列和改數的操作 其實還是因為詢問是最少操作次數 可以想到區間dp。設子狀態 dp i j 表示將區間 i,j 變為回文序列的最少操...
網易面試題 調整隊形
在幼兒園有n個小朋友排列為乙個隊伍,從左到右乙個挨著乙個編號為 0 n 1 其中有一些是男生,有一些是女生,男生用 b 表示,女生用 g 表示。小朋友們都很頑皮,當乙個男生挨著的是女生的時候就會發生矛盾。作為幼兒園的老師,你需要讓男生挨著女生或者女生挨著男生的情況最少。你只能在原隊形上進行調整,每次...