一、單選
1. 80x86中,十進位數-3用16位位元表示為?
解答: 0xFFFD. 資料在電腦裡用補碼錶示,正數的補碼為其原碼,不變,負數的值為其補碼求反加一。最高位為符號位。
因此,可以這樣計算,3減去1,等於2,然後取反,則得到-3的補碼。
2. 假定符號-、*、$分別代表減法、乘法和指數運算,且
三個運算子優先順序順序是:- 最高,*其次,$最低;
運算子運算時為左結合。請計算3-2*4$1*2$3的值:
(A)4096,(B)-61,(C)64,(D)-80,(E)512
解答:-優先順序最高,運算式從左至右計算,先運算3-2,得到1,然後乘以4,得四。由於$d的優先順序最低,所以
接著計算1×2,為2.最後運算式為4$2$3.從左至右計算,為4的2次方,得到16,再3次方,得到4096.
3.下列虛擬碼 中,參數是引用傳遞,結果是?
calc(double p, double q, double r)
{
q=q-1.0;
r=r+p
}
main(
{
double a = 2.5, b = 9.0;
calc(b-a, a, a);
print(a);
}
(A)1.5 (B)2.5 (C)10.5 (D)8 (E)6.5
解答:b-a的結果為6.5,作為一臨時變數傳進去,因此實際計算的運算式為
a = a - 1.0; -> a = 1.5
a = a + 6.5; -> a = 1.5 + 6.5
4、求輸出結果:
int foo(int x, int y)
{
if(x <=0 || y <= 0) return 1;
return 3 * foo(x - 1, y / 2);
}
printf("%d/n", foo(3, 5));
(A)81 (B)27 (C)9 (D)3 (E)16
解答:此題考查遞迴函式的調用, 調用棧順序: foo(3,5) -> 3*foo(2, 2) -> 3*3*foo(1, 1)-> 3 *3*3*f(0,0)
foo(0,0) 返回一,因此結果為27.
5、下列哪個資料 結構在優先隊列中被最廣泛使用
(A)堆 (B)數組 (C)雙向鏈表 (D)圖 (E)向量
解答: 眾所周知優先隊列的實現是基於堆的。因為堆的最小值(最大值)是在堆頂的,這個特性使得實現優先隊列非堆莫屬。
6、以下演算法描述了一個在n國元素的雙向鏈表中找到第k個元素的
方法(k >= 1且k <= n):
如果k <= n - k,從鏈表開始往前進k-1個元素。
否則,從終點出發,往回走n - k個元素。
這個演算法的時間代價是?
(A)θ(nlogn) (B)θ(max{k, n - k}) (C)θ(k + (n - k))
(D)θ(max{k, k - n}) (E)θ(min{k, n - k})
解答:這個演算法的目的就是找比較省時的演算法。所以答案選E.為min(k. n-k).
7、有一個由10個頂點組成的圖,每個頂點有6個度,那麼這個圖有幾條邊?
(A)60 (B)30 (C)20 (D)80 (E)90
解答: 圖論我忘記的差不多了。該怎麼算?
8、RegexL = x*(x|yx+)。下列哪個字串不符號L
(A)x (B)xyxyx (C)xyx (D)yxx (E)yx
重新拿起Regex,好久沒寫了:從左至右,x*表示可以匹配0次或多次x。
再看括弧裡面,x|yx+, 可為x或者是yx++. ,此時注意yx不是整體。
因此xyxyx不匹配。
9、為讀取一塊資料而準備磁碟機的總時間包括:
(A)等待時間 (B)尋道時間 (C)傳輸時間 (D)等待時間加尋道時間
等待時間加尋道時間加傳輸時間
解答:個人覺得答案為D。很不靠譜的答案,這個問題還有待研究。
二、演算法
1、列印出一個二叉樹的內容 。
解答:遞迴列印,先列印左子樹,輸出根節點,再列印右子樹。當然,如果按照樹形來列印的話,就沒有這麼簡單了。
要複雜一點。
2、在一個字串中找到第一個只出現一次的字元。如abaccdeff,輸出b。
可以用簡單的hash方法,使用一個hash數組,hash結果是每個字元的出現次數。
然後從左至右遍曆這個數組的內容,看看誰的值為1即可。
演算法:
char FindEarliestFirstOccurence(const char* str)
{
const char* p = str;
char table[256] = {0};
for (;*p; p++)
{
table[*p]++;
}
const char* q = str;
for (; *q; q++)
if (table[*q] == 1)
return *q;
return 0; // 返回零表示找不到。
}
時間複雜大概為2*strlen(str);還是屬於線性。
3、給定一個長度為N的整數數組(元素有正有負),求所有元素之和
最大的一個子數組。分析演算法時空複雜度。不必寫代碼。
個人感覺此題是求所有元素之和的最大值的變種。(給長度為N的整數數組,有正有負,求子數組之和的最大值)。
方法一: 窮舉法。求最大值。
方法二: 分而治之
方法三: 一個巧妙的方法,邏輯是這樣的,從左至右,求元素之和,如果元素之和為正值,那麼繼續向右。如果元素之和為負值,那麼將這
段元素值和設為零。重新計算元素之和。演算法描述為:
int maxsubsum(const vector<int>& a)
{
int maxsum = 0;
int currentsum = 0;
for(int i = 0; i < N; ++i)
{
currentsum += a[i];
if (currentsum > maxsum)
maxsum = currentsum;
else if (currentsum < 0) // 如果當前段值得和小於0的話,那麼這一段都可以捨棄了,因為其和為負值,最後結果肯定包含他們這一段的。
currentsum = 0;
}
)
有了這個基礎,對於求最大的字數組,求很容易了,拿兩個變數來標識最長字數組的頭和尾就行了。
vector<int> maxsubsum(const vector<int>& a)
{
int maxsum = 0;
int currentsum = 0;
int start = 0;
int end = 0;
vector<int> resultset;
for(size_t i = 0; i < a.size(); ++i)
{
currentsum += a[i];
if (currentsum > maxsum )
{
maxsum = currentsum;
end = i; //end的值會被不斷的更新。用來表示這段字數組的尾部。end隨著maxsum的更新而更新。
}
else if (currentsum < 0)// 如果當前段值得和小於0的話,那麼這一段都可以捨棄了,因為其和為負值,最後結果肯定包含他們這一段的。
{
currentsum = 0;
start = i + 1;
}
}
copy(a.begin() + start, a.begin() + end, back_inserter(resultset)); //複製最長組數組到結果數組。。相當於把從start到end的資料拷貝到結果數組裡去。
return resultset;
}
測試程式:
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
vector<int> a;
copy(istream_iterator<int>(cin),istream_iterator<int>(), back_inserter(a));
vector<int> b;
b = maxsubsum(a);
copy(b.begin(), b.end(), ostream_iterator<int>(cout, " "));
return 0;
}
這個演算法的時間複雜度為o(n).
代碼基本上用c/c++來寫的了,用起來順手一點,題目做的不對的地方,務必請大家指出來。