題目:
陣列中有乙個數字出現的次數超過陣列長度的一半,請找出這個數字。例如輸入乙個長度為9的陣列。由於數字2在陣列中出現了5次,超過陣列長度的一半,因此輸出2.
分析:
看到這個題的時候我首先想的是加乙個輔助陣列,統計出每乙個數出現的次數,因為題目中給的陣列是不知道的所以不能用雜湊儲存的方法,那麼只能用普通方法,則對其查詢的時間複雜度就是o(n2)。所以這個方式肯定是不合適的。
那麼我們就又再想如果這個陣列是排序的話,那麼是不是會方便一些,肯定會方便一些,排序的時間複雜度是o(nlgn)。
如果說還有更快的,你能想到嗎?
方法1:
仔細分析題目咱們會發現題目中所說的超過一半這個問題,咱們一直把它當做問題,用來最後判斷是不是符合條件,那麼咱們能不能把它翻過來用,讓這個問題轉化成我們的條件? 對!如果把陣列排序的話,那麼超過一半的數,肯定位於中間,所以也就是說那個超過一半的數字,肯定是這個陣列的中位數!我們再努力一點,想啊!如果是中位數的話,那麼是不是就是它的左邊都比它小或者等於,右邊都比它大或者等於!
這時如果我們能把只是遷移一下就會意識到快速排序中的partition()函式的作用,它隨機選取乙個數,讓比它大的都在右邊,比它小的都在左邊。這不正是我們需要的嗎!?
也就是說如果這個隨機數正好位於中間的話,那麼這個數就是我們需要的啦!!
方法2;
接下來我們從另外乙個角度分析來解決這個問題,我們還是抓住陣列中有乙個數字出現的次數超過陣列長度的一半,這句話來當突破口。也就是說有乙個數字出現的次數比其他所有的數字出現的總和還要多。因此我們可以考慮在遍歷陣列的時候儲存兩個值:乙個是陣列中的乙個數字,乙個是次數。當我們遍歷到下乙個數字的時候,如果下乙個數字和我們之前儲存的數字相同,則次數加1,如果不同則次數減1,如果次數為0,就儲存下乙個數字,並把次數設定為1,由於我們要找的數字出現的次數比其他所有數字出現的次數之和還要多,那麼要找的數字肯定是最後一次把次數設為1時對應的數字。
方法1的**:
#include #include #include using namespace std;bool g_binputinvalid = false;
int random(int start,int end)
void swap(int *a,int *b)
int partation(int *data,int length ,int start,int end)
else
}int result = data[middle];
if(!checkmorethanhalf(data,length,result))
result = 0;
cout<<"找到了!"<
方法2**:
int morethanhalfnumfangfa2(int *data,int length)
{ if(data == null && length < 0)
{cout<<"陣列錯誤"<
劍指offer 29陣列中出現次數超過一半的數字
題目 陣列中有乙個數字出現的次數超過陣列長度的一半,請找出這個數字。例如輸入乙個長度為9的陣列。由於數字2在陣列中出現了5次,超過陣列長度的一半,因此輸出2。如果不存在則輸出0。拿到題目的第一反應是將陣列排序,然後判斷陣列中間的數字長度是否超過陣列長度的一半。若陣列中出現最多次數的數字為0且長度超過...
劍指offer 29 陣列中出現次數超過一半的數字
陣列中有乙個數字出現的次數超過陣列長度的一半,請找出這個數字。例如輸入乙個長度為9的陣列。由於數字2在陣列中出現了5次,超過陣列長度的一半,因此輸出2。如果不存在則輸出0。如果某個數符合條件,它一定是中位數。因此,找出中位數。如果乙個數num,左邊比它小,右邊比它大,它的下標是index。如果ind...
offer29 陣列中出現次數超過一半的數字
coding utf 8 offer29 最開始儲存兩個數值 陣列中的乙個數字以及它出現的次數,然後遍歷,如果下乙個數字等於這個數字,那麼次數加一,如果不等,次數減一,當次數等於0的時候,在下乙個數字的時候重新複製新的數字以及出現的次數置為1,直到進行到最後,然後再驗證最後留下的數字是否出現次數超過...