大小為下面是求解該問題的乙個演算法概要。n 的陣列
a,其主要元素是乙個出現次數超過n/
2 的元素(從而這樣的元素最多有乙個)。例如,陣列 3,
3,4,
2,4,
4,2,
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, 編寫乙個程式求解主要元素.
n 為偶數的情況。
我們需要回答這樣乙個問題:
b中的候選元也是
a 中的候選元。
反證法假設m
是a的候選元在陣列
b中的出現次數,
n 是陣列
b中其他元素的個數,即: m+
n=m
其中m是陣列b的大小。
顯然,m
而2m+
2n+l
=n其中l 是
ai、a
i+1 不相同的元素個數。
l 所覆蓋的元素最多只有l/
2個a 的候選元。所以說,
a的候選元個數為2m
+l/2
。 2m+
l2−n
2=4m
+n−2
m−2n
−n2=
m−n<0
所以a中候選元的個數要小於n/
2,假設矛盾,證畢。
好了,到此,我們是時候拿起減而治之這個有力的**了。
我們可以將問題
a 化簡為
b,而問題規模減小一半,不斷的重複,直至陣列規模為1或者0。
當然,別忘記
n 為奇數的情況,我們還需要做些小修改。當n
為奇數時,先從前n−
1 個元素中尋找主元:
1. 如果找到主元確實存在,那麼直接返回主元即可。
2. 否則,第
n 個元素可能是主元,我們需要遍歷陣列來確定它是否真的是主元。
對於偶數: t(
n)=t
(n/2
)+n不難解出 o(
n)=n
對於奇數,確認主元存在需要o(
n)的時間,遍歷陣列也需要o(
n)的時間,總之是o(
n)的時間。
最後附上**
bool ismainelement(vector
&v)
if (count>v.size() / 2)
return
true;
else
return
false;
}int findmainelement(vector
&v)
int res = findmainelement(u);
if (v.size() % 2 != 0 && res == -1 && ismainelement(v))
return v.back();
else
return res;
}
219 存在重複元素 II
219.存在重複元素 ii 給定乙個整數陣列和乙個整數 k,判斷陣列中是否存在兩個不同的索引i 和j,使得nums i nums j 並且 i 和 j 的差的絕對值最大為 k。示例 1 輸入 nums 1,2,3,1 k 3 輸出 true 示例 2 輸入 nums 1,0,1,1 k 1 輸出 t...
219 存在重複元素 II
鏈結 給定乙個整數陣列和乙個整數 k,判斷陣列中是否存在兩個不同的索引 i 和 j,使得 nums i nums j 並且 i 和 j 的差的絕對值最大為 k。示例1 輸入 nums 1,2,3,1 k 3 輸出 true示例2 輸入 nums 1,0,1,1 k 1 輸出 true示例3 輸入 n...
219 存在重複元素 II
給定乙個整數陣列和乙個整數 k,判斷陣列中是否存在兩個不同的索引 i 和 j,使得 nums i nums j 並且 i 和 j 的差的絕對值最大為 k。示例 1 輸入 nums 1,2,3,1 k 3 輸出 true 示例 2 輸入 nums 1,0,1,1 k 1 輸出 true 示例 3 輸入...