一、三個問題
1、給定一個最多包含40億個隨機排列的32位整數的順序文件,找出一個不在文件中的32位整數。分別考慮在有足夠內存或有幾個外部臨時文件可用,但僅有幾百字節的內存的情況下,如果解決問題;
2、將一個n元一維向量向左旋轉i個位置,例如,當n=8且i=3時,向量abcdefgh旋轉爲defghabc;
3、給定一個英語字典,找出其中的所有變位詞集合。例如,“pots”、“stop”、“tops”互爲變位詞,因爲每個單詞都可通過改變其他單詞中字母的順序來得到。
二、問題解決
1、對於第一個問題,如果內存足夠,則可以採用第(1)節中的位圖技術,使用536870912個8位字節形成位圖來表示已看到的整數,然而,若僅有幾百字節,則考慮使用二分搜索技術來解決。爲了採用二分搜索技術,必須定義一個範圍、在該範圍內表示元素的方式以及用來確定哪一半範圍存在缺失整數的探測方法。
我們採用已知包含至少一個缺失元素的一系列整數作爲範圍,並使用包含所有這些整數在內的文件表示這個範圍。通過統計中間點之上和之下的元素來探測範圍:或者上面或者下面的範圍具有之多全部範圍的一半元素。由於整個範圍中有一個缺失元素,因此我們所需的那一半範圍中必然也包含缺失的元素。這些就是解決問題的二分搜索算法所需的主要思想。
2、對於第二個問題,我們將問題看做是把數組ab轉換成ba,同事假定我們擁有一個函數可以將數組中特定部分的元素求逆。從ab開始,首先對a求逆,得到a'b,然後對b求逆,得到a‘b’,最後整體求逆,得到(a‘b’)‘,此時就恰好是ba了。具體做法如下面代碼所示:
reverse(0,i-1); //cbadefgh
reverse(i,n-1); //cbahgfed
reverse(0,n-1); //defghabc
3、對於第三個問題,可以通過標識字典中的每一個詞,使得在相同變位詞類中的單詞具有相同的標識。然後將所有具有相同標識的單詞集中在一起。這將原始的變位詞問題簡化爲兩個問題:選擇標識和集中具有相同標識的單詞。
對於標識。當使用等價關係來定義類時,定義一種標識使得類中的每一項都具有相同的標識,而該類以外的其他項則沒有該標識。可使用一個計數來代表重複的次數,例如(1)mississippi可以寫成i4m1p2s4或者1省略就是i4mp2s4,也可(2)使用一個包含26個整數的數組來表示每個字母出現的次數。
以下是變位詞程序的實現:
int charcmp(char *a,char *b)
{
return *a - *b;
}
#define WORDMAX 100
int main(void)
{ char word[WORDMAX],sign[WORDMAX];
while(scanf(%s,word) != EOF)
{ strcpy(sign,word);
qsort(sign,strlen(sign),sizeof(char),charcmp); //排序單詞內的字符
printf("%s %s\n",word,sign);
}
return 0;
}
//輸出相同簽名的 變位詞 到單行squash
int main()
{ char word[WORDMAX],sign[WORDMAX],oldsign[WORDMAX];
int linenum = 0;
while(scanf("%s %s",word,sign) != EOF)
{ oldsign = sign;
if(strcmp(sign,oldsign) != 0 && linenum > 0) //判斷是否sig與oldsig(其上一次的值)不同
printf("\n");
strcpy(oldsign,sign);
linenum++;
printf("%s ",word);
}
printf("\n");
return 0;
}
sign < dictionary | sort | squash > gramlist