陣列中有乙個數字出現的次數超過陣列長度的一半,請找出這個數字。例如輸入乙個長度為9的陣列。由於數字2在陣列中出現了5次,超過陣列長度的一半,因此輸出2。如果不存在則輸出0。
需要找的數字超過陣列長度的一半,那麼如果對它進行排序,再取數姐中間那個數字即為所求,但是這種做法的時間複雜度最少為o(nlogn),如果需要要控制到o(n),可以採用下面三種方式。
我們使用兩個變數分別儲存陣列中的乙個數字以及次數(不是出錯的總次數喲!)。然後遍歷陣列,發現如果遍歷的數字跟我們儲存的數字一樣,則次數加1,否則減1;如果次數為0,則儲存此刻遍歷的數字,次數記為1.原理是什麼呢?這相當於同時刪掉兩個不同的數,因為我們要找的數的個數大於陣列長度,所以如果按這種方法計算的話,剩下的即為我們要找的。但是我們也要考慮到非法輸入的情況,假如我們傳入的容器值為0,或者我們輸入的數字序列沒有次數超過陣列長度一半的怎麼辦?這時,我們就需要設定乙個非法輸入判定函式。
class solution else if(result == numbers[i])
counts ++;
else
}if(!checkmorethanhalf(numbers,result))
result = 0;
return result;
}bool checkmorethanhalf(vectornumbers, int find)
if(count * 2 <= len)
return false;
return true;
}};
另外一種方法是,是使用c++的map容器,健為陣列元素,它的健值為該數字出現的次數。如果出現次數大於長度的一半,即我們需要找的值,如果遍歷完,仍然沒有出現長度大於一半的值,則返回0;這種方法,可以不用寫非法輸入的判定式了!很奇怪,我覺得map很好用呀,為什麼那麼多解析書上都會用雜湊表,我覺得還要設定乙個陣列麻煩多了。是不是記憶體的原因?待解。
class solution
return 0;
}};
第三種方法是借用於快排的思想,快排裡面可以使用partition函式來劃分值,把小於分界線的放在右邊,大於分界值的放在左邊,我們可以找到陣列中值的partition序列,然後取中值 即為所求。
class solution2
else
} if(!checkmorethanhalf(numbers, numbers[mid]))
return 0;
return numbers[mid];
} int partition(vector&numbers, int start, int end)
//隨機選擇乙個數
int index = (rand()%(end - start)) + start;
swap(numbers[index], numbers[end]);
int small = start -1;
for(int i = start; i < end; i ++)
} small ++;
swap1(numbers[small], numbers[end]);
return small;
} void swap1(int& a, int& b)
bool checkmorethanhalf(vectornumbers, int find)
if(count * 2 <= len)
return false;
return true;
}};
陣列中出現次數超過一半的數字
何海濤 劍指offer 名企面試官精講典型程式設計題 九度oj 題目描述 陣列中有乙個數字出現的次數超過陣列長度的一半,請找出這個數字。例如輸入乙個長度為9的陣列。由於數字2在陣列中出現了5次,超過陣列長度的一半,因此輸出2。輸入 每個測試案例包括2行 第一行輸入乙個整數n 1 n 100000 表...
陣列中出現次數超過一半的數字
陣列中出現次數超過一半的數字 陣列中有乙個數字出現的次數超過陣列長度的一半,請找出這個數字。例如輸入乙個長度為9的陣列。由於數字2在陣列中出現了5次,超過陣列長度的一半,因此輸出2。如果不存在則輸出0。class solution count 0 for auto i numbers if i k ...
陣列中出現次數超過一半的數字
題目描述 陣列中有乙個數字出現的次數超過陣列長度的一半,請找出這個數字。例如輸入乙個長度為9的陣列。由於數字2在陣列中出現了5次,超過陣列長度的一半,因此輸出2。如果不存在則輸出0。解題思路 將陣列按大小排序,若存在數字出現次數超過陣列長度的一般,則陣列中位數必定為該數字 1 將陣列排序完成後,取a...