C++實(shí)現(xiàn)LeetCode(169.求大多數(shù))
[LeetCode] 169. Majority Element 求大多數(shù)
Given an array nums of size n, return the majority element.
The majority element is the element that appears more than ⌊n / 2⌋ times. You may assume that the majority element always exists in the array.
Example 1:
Input: nums = [3,2,3]
Output: 3
Example 2:
Input: nums = [2,2,1,1,1,2,2]
Output: 2
Constraints:
- n == nums.length
- 1 <= n <= 5 * 104
- -231 <= nums[i] <= 231 - 1
Follow-up: Could you solve the problem in linear time and in O(1) space?
這是到求大多數(shù)的問(wèn)題,有很多種解法,其中我感覺(jué)比較好的有兩種,一種是用哈希表,這種方法需要 O(n) 的時(shí)間和空間,另一種是用一種叫摩爾投票法 Moore Voting,需要 O(n) 的時(shí)間和 O(1) 的空間,比前一種方法更好。這種投票法先將第一個(gè)數(shù)字假設(shè)為過(guò)半數(shù),然后把計(jì)數(shù)器設(shè)為1,比較下一個(gè)數(shù)和此數(shù)是否相等,若相等則計(jì)數(shù)器加一,反之減一。然后看此時(shí)計(jì)數(shù)器的值,若為零,則將下一個(gè)值設(shè)為候選過(guò)半數(shù)。以此類(lèi)推直到遍歷完整個(gè)數(shù)組,當(dāng)前候選過(guò)半數(shù)即為該數(shù)組的過(guò)半數(shù)。不仔細(xì)弄懂摩爾投票法的精髓的話(huà),過(guò)一陣子還是會(huì)忘記的,首先要明確的是這個(gè)叼炸天的方法是有前提的,就是數(shù)組中一定要有過(guò)半數(shù)的存在才能使用,下面來(lái)看本算法的思路,這是一種先假設(shè)候選者,然后再進(jìn)行驗(yàn)證的算法?,F(xiàn)將數(shù)組中的第一個(gè)數(shù)假設(shè)為過(guò)半數(shù),然后進(jìn)行統(tǒng)計(jì)其出現(xiàn)的次數(shù),如果遇到同樣的數(shù),則計(jì)數(shù)器自增1,否則計(jì)數(shù)器自減1,如果計(jì)數(shù)器減到了0,則更換下一個(gè)數(shù)字為候選者。這是一個(gè)很巧妙的設(shè)定,也是本算法的精髓所在,為啥遇到不同的要計(jì)數(shù)器減1呢,為啥減到0了又要更換候選者呢?首先是有那個(gè)強(qiáng)大的前提存在,一定會(huì)有一個(gè)出現(xiàn)超過(guò)半數(shù)的數(shù)字存在,那么如果計(jì)數(shù)器減到0了話(huà),說(shuō)明目前不是候選者數(shù)字的個(gè)數(shù)已經(jīng)跟候選者的出現(xiàn)個(gè)數(shù)相同了,那么這個(gè)候選者已經(jīng)很 weak,不一定能出現(xiàn)超過(guò)半數(shù),此時(shí)選擇更換當(dāng)前的候選者。那有可能你會(huì)有疑問(wèn),那萬(wàn)一后面又大量的出現(xiàn)了之前的候選者怎么辦,不需要擔(dān)心,如果之前的候選者在后面大量出現(xiàn)的話(huà),其又會(huì)重新變?yōu)楹蜻x者,直到最終驗(yàn)證成為正確的過(guò)半數(shù),佩服算法的提出者啊,代碼如下:
C++ 解法一:
class Solution {
public:
int majorityElement(vector<int>& nums) {
int res = 0, cnt = 0;
for (int num : nums) {
if (cnt == 0) {res = num; ++cnt;}
else (num == res) ? ++cnt : --cnt;
}
return res;
}
};
Java 解法一:
public class Solution {
public int majorityElement(int[] nums) {
int res = 0, cnt = 0;
for (int num : nums) {
if (cnt == 0) {res = num; ++cnt;}
else if (num == res) ++cnt;
else --cnt;
}
return res;
}
}
下面這種解法利用到了位操作 Bit Manipulation 來(lái)解,將這個(gè)大多數(shù)按位來(lái)建立,從0到31位,每次統(tǒng)計(jì)下數(shù)組中該位上0和1的個(gè)數(shù),如果1多,那么將結(jié)果 res 中該位變?yōu)?,最后累加出來(lái)的 res 就是過(guò)半數(shù)了,相當(dāng)贊的方法,參見(jiàn)代碼如下:
C++ 解法二:
class Solution {
public:
int majorityElement(vector<int>& nums) {
int res = 0, n = nums.size();
for (int i = 0; i < 32; ++i) {
int ones = 0, zeros = 0;
for (int num : nums) {
if (ones > n / 2 || zeros > n / 2) break;
if ((num & (1 << i)) != 0) ++ones;
else ++zeros;
}
if (ones > zeros) res |= (1 << i);
}
return res;
}
};
Java 解法二:
public class Solution {
public int majorityElement(int[] nums) {
int res = 0, n = nums.length;
for (int i = 0; i < 32; ++i) {
int ones = 0, zeros = 0;
for (int num : nums) {
if (ones > n / 2 || zeros > n / 2) break;
if ((num & (1 << i)) != 0) ++ones;
else ++zeros;
}
if (ones > zeros) res |= (1 << i);
}
return res;
}
}
Github 同步地址:
https://github.com/grandyang/leetcode/issues/169
類(lèi)似題目:
參考資料:
https://leetcode.com/problems/majority-element/
https://leetcode.com/problems/majority-element/discuss/51613/O(n)-time-O(1)-space-fastest-solution
到此這篇關(guān)于C++實(shí)現(xiàn)LeetCode(169.求大多數(shù))的文章就介紹到這了,更多相關(guān)C++實(shí)現(xiàn)求大多數(shù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- C++實(shí)現(xiàn)LeetCode(188.買(mǎi)賣(mài)股票的最佳時(shí)間之四)
- C++實(shí)現(xiàn)LeetCode(557.翻轉(zhuǎn)字符串中的單詞之三)
- C++實(shí)現(xiàn)LeetCode(186.翻轉(zhuǎn)字符串中的單詞之二)
- C++實(shí)現(xiàn)LeetCode(173.二叉搜索樹(shù)迭代器)
- C++實(shí)現(xiàn)LeetCode(172.求階乘末尾零的個(gè)數(shù))
- C++實(shí)現(xiàn)LeetCode(170.兩數(shù)之和之三 - 數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì))
- C++實(shí)現(xiàn)LeetCode(309.買(mǎi)股票的最佳時(shí)間含冷凍期)
相關(guān)文章
C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易連連看游戲
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)簡(jiǎn)易連連看游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
C++使用new和delete進(jìn)行動(dòng)態(tài)內(nèi)存分配與數(shù)組封裝
這篇文章主要介紹了C++使用new和delete進(jìn)行動(dòng)態(tài)內(nèi)存分配與數(shù)組封裝,運(yùn)行期間才能確定所需內(nèi)存大小,此時(shí)應(yīng)該使用new申請(qǐng)內(nèi)存,下面我們就進(jìn)入文章學(xué)習(xí)具體的操作方法,需要的小伙伴可以參考一下2022-03-03
VisualStudio Community2019在安裝的過(guò)程中無(wú)法進(jìn)入安裝界面的解決方法
這篇文章主要介紹了VisualStudio Community2019在安裝的過(guò)程中無(wú)法進(jìn)入安裝界面的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03
C++示例講解friend static const關(guān)鍵字的用法
靜態(tài)成員static是解決同一個(gè)類(lèi)的不同對(duì)象之間數(shù)據(jù)和函數(shù)共享問(wèn)題。區(qū)分全局變量,全局變量也能實(shí)現(xiàn)數(shù)據(jù)共享,但安全性和封裝性被破壞了,友元提供了不同類(lèi)或?qū)ο蟮某蓡T函數(shù)之間、類(lèi)的成員函數(shù)與一般函數(shù)之間進(jìn)行數(shù)據(jù)共享的機(jī)制,const常引用-被引用的對(duì)象不能被更新2022-06-06
C語(yǔ)言實(shí)現(xiàn)手寫(xiě)字符串處理工具的示例代碼
這篇文章主要為大家詳細(xì)介紹了利用C語(yǔ)言實(shí)現(xiàn)手寫(xiě)字符串處理工具的相關(guān)資料,文中的示例代碼講解詳細(xì),具有一定的借鑒價(jià)值,需要的可以參考一下2022-09-09
C++11中列表初始化機(jī)制的概念與實(shí)例詳解
在我們實(shí)際編程中,我們經(jīng)常會(huì)碰到變量初始化的問(wèn)題,對(duì)于不同的變量初始化的手段多種多樣,下面這篇文章主要給大家介紹了關(guān)于C++11中列表初始化機(jī)制的相關(guān)資料,需要的朋友可以參考下2021-11-11

