PAT-B 1048. 數字加密(20)
阿新 • • 發佈:2019-01-26
題目連結在此。
思路及AC程式碼
我們用字串陣列儲存兩個輸入,由於兩個字串的長度可能不相等,為了方便兩個字串的相同位進行運算,我們有兩種解決思路:
我的思路
記錄兩個字串的長度分別為lena,lenb,lena和lenb作比較,稍長的那個記作len_max,兩個長度差值的絕對值記作dis。
想將稍短的字串所有位都向後移動dis個位置,前面0~dis-1的位置補上’0’,這樣之後,兩個字串就對對齊了,直接實現題目中的演算法即可。
但是這種思路會遇到一個坑:奇數位和偶數位的判定。
這裡只稍做根本原因上的提示,至於判定方法,非常多樣,只需要能夠判定方法能夠做到奇偶交替,和題目中要求的奇偶性對上即可。
“坑”的提示:
由於從右往左的第一位為奇數位,當len_max=4時,從左往右的第一位為偶數位,len_max=5時,* 從左往右*的第一位為奇數位。
AC程式碼
#include<stdio.h>
#include<string.h>
char mp[] = {'0','1','2','3','4','5','6','7','8','9','J','Q','K'};
int main(){
char a[101],b[101];
scanf("%s %s",a,b);
int lena = strlen(a);
int lenb = strlen(b);
int len_max = (lena > lenb) ? lena : lenb;
//先移動元素,使得a,b陣列元素對齊
if(lena < lenb){
int dis = lenb-lena;
//a往後移動dis個位置
for(int i = lena-1; i >= 0; i--){
a[i+dis] = a[i];
}
//給a陣列的0~dis-1賦值為'0'
for(int i = 0; i < dis; i++){
a[i] = '0' ;
}
} else if(lena > lenb){
int dis = lena-lenb;
for(int i = lenb-1; i >= 0; i--){
b[i+dis] = b[i];
}
for(int i = 0; i < dis; i++){
b[i] = '0';
}
}//else lena==lenb ,則可直接運算
//實現題目演算法
int res;
int index = 0;
for(int i = 0; i < len_max; i++){
//尤其注意奇偶性的判定
if((len_max-i+1)%2){ //對應於題目的偶數位情況
res = (b[i]-'0')-(a[i]-'0');
if(res<0){
res += 10;
}
printf("%c",mp[res]);
} else{ //對應於題目的奇數位情況
res = ((a[i]-'0')+(b[i]-'0'))%13;
printf("%c",mp[res]);
}
}
return 0;
}
《演算法筆記》思路
《演算法筆記》的思路在大體上和我的一致,兩者的區別也就差在如何對齊上。
《演算法筆記》中的對齊是將兩個字串都逆序儲存,在短的那個字串的後面補上dis個’0’,之後的演算法實現就和上面的一致了。
但是這種方法完美的避開了上面所提及的“坑”,因為這種方法奇偶性的判定完畢之後,直接和逆序之前的奇偶性是相反的(迴圈變數從左往右,從0開始,才有相反這個結論。如果從1開始,則奇偶性相同。主要還是和題目本身的奇偶性對應起來考慮即可。)。 比如:現在的從左往右第一位開始時i=0,i是偶數,而這一位本來應該是奇數位才對,因為這一位對應的是逆序前從右往左的左後一位。(似乎有點繞,需仔細思考)
這個演算法主要就是陣列逆序的實現,之後就和第一種思路的實現大同小異,暫時不貼程式碼了。