題目描述:
大小為n的陣列a,其主要元素就是乙個出現次數超過n/2的元素(從而這樣的元素只有乙個或者不存在) . 例如, 陣列
3, 3, 4, 2, 4, 4, 2, 4, 4
有乙個主要元素4, 而陣列
3, 3, 4, 2, 4, 4, 2, 4
沒有主要元素. 如果沒有主要元素, 那麼你的程式應該指出來. 下面是求解該問題的乙個演算法的框架:
首先找出主要元素的乙個候選元(這是難點)。這個候選元是唯一有可能是主要元素的元素。第二步確定是否這個候選元是主要元素。為了找出候選元,構造第二個陣列b。比較a1和a2,如果它們相等則取其中之一加到陣列b中;否則什麼都不做;然後比較a3和a4,按同樣的方式處理,其次類推直到讀完這個陣列,然後遞迴的尋找陣列b中的候選元,它也是a的候選元. (為什麼?)
a, 遞迴如何終止?
b, 當n是奇數時, 如何處理?
c, 該演算法的執行時間是多少?
d, 我們如何避免使用附加陣列b?
e, 編寫乙個程式求解主要元素.
自己寫的考慮不全面,還是參考網上有嚴謹證明思路,效率最高的實現吧。
解答:a, 當陣列b的元素個數等於0或者1時, 遞迴終止
b, 如果前n-1個元素有主元, 那麼最後乙個元素不管是不是主元都對結果沒有影響;
如果前n-1個元素沒有主元, 那麼加上最後乙個元素之後, 就有可能使整個陣列存在主元, 所以最後乙個元素有可能是主元
所以最後的演算法應該是這樣的:
如果陣列元素的個數是偶數, 就找出候選元, 然後再遍歷整個陣列, 確定這個候選元是否是主元
如果陣列元素的個數是奇數, 那麼就先從前n-1個元素中找出候選元,
遍歷整個陣列, 如果這個候選元就是主元, 那麼就結束了,
遍歷整個陣列, 如果這個候選元不是主元, 那麼就把最後乙個元素當做候選元, 再遍歷陣列, 確定這個候選元是否就是主元
c, 對於偶數, t(n) = t(n/2) + n
根據master定理: a = 1, b = 2, logba = 0, f(n) = o(1), f(n) > n logba 所以t(n) = o(n).
對於奇數, 只多了一次遍歷, 所以t(n) = o(n) + o(n) = o(n)
d, 仍然是陣列中的每兩個元素相比較, 先比較a1和a2, 如果相等就和陣列最前面的元素交換, 如果不相等就不交換, 再比較a3和a4, 如果相等就和前乙個比較之後交換過的元素的下乙個位置的元素交換, 如果不相等就不交換, 按同樣的方式處理,其次類推直到讀完這個陣列,然後遞迴的尋找陣列b中的候選元,它也是a的候選元.
e, **:
#include #include using namespace std;
#define notamaincell -100
void swap(int &a, int &b)
bool ismaincell(vector&arr, int probablymaincell)
int findmaincell(vector&arr, int p)
for (int i = 0, len = 0; i < p; i = i + 2)
else if (i == p - 3)
else
return result;
} }}int main()
; vectorarr1 = ;
int result = findmaincell(arr, arr.size());
if (result == notamaincell)
cout << "沒有主元" << endl;
else
cout << "主元是" << result << endl;
return 0;
}
參考:
資料結構與演算法分析C語言描述 1 1
include include 將前k個元素讀入陣列並 以遞減的順序 對其排序。接著,將剩下的元素再逐個讀入 如果它小於陣列中的第k個元素則忽略 否則 就將其放到陣列中正確的位置上,同時將陣列中的乙個元素擠出陣列 define swap x,y,t t x x y y t int key int a...
資料結構與演算法分析
資料結構與演算法分析可以稱得上是程式設計師必須修煉的內功心法。資料的儲存結構 資料元素在計算機中的儲存方式 資料的操作集合 對一種資料型別的資料所有操作,例如對資料的增刪改查等等!演算法分析主要分析 下面是一些常用資料結構 一 線性表 1.陣列實現 2.鍊錶 二 棧與佇列 三 樹與二叉樹 1.樹2....
資料結構與演算法分析
資料結構 大量資料的組織方法 演算法分析 演算法執行時間的估算。涉及到計算效率。設想,如果能把時間限制從16年減至不到1秒,不很神奇嗎?在很多問題中,乙個重要的觀念是 寫出乙個可以工作的程式並不夠。如果這個程式在巨大的資料集上執行,執行時間就成了重要的 問題。演算法,是為求解乙個問題需要遵循的 被清...