算法小測試

算法小測試

實驗室大師兄開了個小灶,講了一些簡單的算法題給我們開拓一下思路?,F(xiàn)在把這次講到的幾個測試題記錄在這里,一來是再過一遍加深印象,二來以后也可以看看。

測試題1--判斷和為s的元素的存在性

題目:已知數(shù)組a[0],a[1],...,a[i],a[i+1],...,a[n]以及一個整數(shù)s;其中n范圍為10^5,a[i]的范圍為10^9,判斷數(shù)組a[n]中是否存在a[i]a[j],使得s=a[i]+a[j],其中i可以等于j

我的思路:最快能想到的自然是枚舉法,就是將數(shù)組a[n]中的每兩個元素都相加看能不能等于s,但是這個方法很蠢,時間復(fù)雜度是o(n^2)。
那有沒有更好的方法?當(dāng)然有,其實這種從數(shù)組中找數(shù)的題如果一遍遍歷無法解決問題,那么就要先進行一下排序處理了,雖然排序過程會增加復(fù)雜度,但是排序后就可以利用元素之間的相關(guān)信息解題,事半功倍。
所以先對數(shù)字進行排序,方法很多,快排來做就是o(nlog(n))。
堆排序后的數(shù)組從兩頭開始遍歷,i=0開始,j=n開始,此時a[i]最小,a[j]最大。然后按照下面的規(guī)則進行移動:

<pre>
while(i<=j){
if a[i]+a[j]==s
return true;
else if a[i]+a[j]<s
i++;
else if a[i]+a[j]>s
j--;
}
return false;
</pre>

這種方法對于排序后的數(shù)組來說得到結(jié)果的時間復(fù)雜度是o(n);再考慮前面排序的過程,整體的復(fù)雜度就是max(o(nlog(n)),o(n))=o(nlog(n))。

要理解這種方法其實可以把a[i]+a[j]想象為一個二維矩陣,縱軸和橫軸都是a[0]...a[n],形狀如:
<pre>
--------------------------------->
| a[0], a[1], a[2],..., a[n]
| a[0] - - - -
| a[1] - - - -
| ...
| a[n] - - - -
/
</pre>

矩陣中元素的特點是隨著箭頭的方向,矩陣中元素所對應(yīng)橫縱坐標a[i]和a[j]之和不斷增大。再明顯點就是:
<pre>
--------------------------------->
| a[0], a[1], a[2],..., a[n]
| a[0] 小 小 小 未2
| a[1] 小 小 X 大
| ...
| a[n] 未1 未1 大 大
/
</pre>

矩陣中每個元素的值都是其橫縱坐標a[i]與a[j]的和,當(dāng)前位置為X,“小”對應(yīng)位置的值小于“X”對應(yīng)的值,“大”對應(yīng)位置的值大于“X”對應(yīng)的值,剩余的“未1”和“未2”對應(yīng)的值和“X”的關(guān)系是未知的。這道題就轉(zhuǎn)化為判斷在這個矩陣中是否存在值為s的元素。
現(xiàn)在假設(shè)當(dāng)前值x比s小,說明“小”對應(yīng)的值都要小于s,那么我們應(yīng)該在“大”,“未1”和“未2”中繼續(xù)找;反之亦然,當(dāng)前置x比s大時,說明“大”對應(yīng)的值都要大于s,那么我們就應(yīng)該在“小”,“未1”和“未2”中繼續(xù)找。這個過程就是對搜索區(qū)域進行簡化排除的過程。
那么現(xiàn)在又有一個問題,這每一次的簡化得到的剩余的區(qū)域是個多邊形,并不是矩形,不能很好的實現(xiàn)在一個矩形模板上簡化問題的目的。如何才能做到每一次簡化后剩余的還是一個矩形呢。很簡單,直到隨意選擇左下角或者右上角作為起始判斷位置,然后進行簡化就可以了。比如從右上角開始,那么第一次簡化時x>s就可以排除最右邊那一列,如果x<s就可以排除最上邊那一行,剩下的就還是一個矩形了。然后不斷簡化,直到排除掉所有的元素,或者找到x==s時為止,問題就解決了。
把這個理論實現(xiàn)為代碼時就是像上面的偽代碼一樣,從最左和最右同時開始遍歷。
當(dāng)然還有很多其他的方法可以解這道題,但是這種方法應(yīng)該是時間復(fù)雜度最小的了,如果有人有更好的方法可以下來交流。

測試題2--計算三角形面積

題目:給定一個三角形三個定點的坐標,計算這個三角形的面積。
解法:這個題有很多解法,較簡單的就是通過公式計算,比如:

  1. 海倫公式:sqrt(d(d-a)(d-b)(d-c)),其中a,b,c為三角形的三邊長,d為三邊和的一般,就是d=(a+b+c)/2;這種解法需要使用公式先計算出三條邊的長度。算法缺點就是計算機計算時會有誤差存在。
  2. 使用面積=底×高/2的公式,同樣的也需要使用其他公式計算高,還有邊長,缺點也是會有誤差。
  3. 利用向量外積公式:向量的外積還是一個向量,新向量的模為:|AB×AC|=(|AB|×|AC|×sin(θ));三角形面積=(1/2)(AB×AC)=(1/2)(|AB|×|AC|×sin(θ));所以可以根據(jù)向量的外積得到三角形的面積。外積的坐標表示為:(x1,y1,z1)×(x2,y2,z2)=(y1z2-y2z1,z1x2-z2x1,x1y2-x2y1),向量的外積是建立在三維空間上的,我們要求三角形的面積就可以把其中一個維度的坐標定位0,比如z1=z2=0,這樣就得到(x1,y1,0)×(x2,y2,0)=(0,0,x1y2-x2y1)。假設(shè)三點A(x1,y1),B(x2,y2),C(x3,y3),則AB=(x2-x1,y2-y1),AC=(x3-x1,y3-y1);則面積=(1/2)|AB×AC|=(1/2)((x2-x1)×(y3-y1)-(y2-y1)×(x3-x1));
  4. 多邊形面積公式:就是將多邊形分割為多個三角形,然后求所有三角形的總和,所以本質(zhì)也是利用了上邊的向量外積公式。

測試題3--求最短距離

題目:在二維直角坐標系中有一個與坐標平行的矩陣,給出這個矩陣的四個點A,B,C,D的坐標,以及一個矩陣外的P點坐標,計算P點到矩陣邊界上任意一點的距離中的最短距離。

我的思路:這個題最開始我想到的是把矩形的四條邊無限延長,這樣坐標系就被分為了8個區(qū)域,當(dāng)P點在這8個區(qū)域中的正上下左右方時,最短距離就是P點橫坐標和縱坐標與A,B,C,D四個點坐標的橫坐標和縱坐標差值中的最小值;而當(dāng)P點在剩余的四個區(qū)域時,最短距離就是P點和A,B,C,D四個點距離中的最小值。
我的這個思路當(dāng)然是可行的,但是不夠簡潔,雖然和最優(yōu)答案很接近了,但是沒有抓住本質(zhì)。下面來說以下更好的解法。

假定最短連線中除P(p1,p2)點外的另一個點為S(s1,s2),那么s1=max(min(a1,b1),min(max(a1,b1),p1));s2=max(min(a2,c2),min(max(a2,c2),p2)),然后直接求SP的距離就可以了。這里的s1就是a1,b1和p1三個數(shù)排序后位于中間的那個數(shù)的值,s2就是a2,c2和p2三個數(shù)排序后位于中間的那個數(shù)的值。


。。。未完待續(xù)。。。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容