多數(shù)元素

多數(shù)元素

也叫數(shù)組中出現(xiàn)次數(shù)超過(guò)一半的數(shù)字

給定一個(gè)大小為 *n *的數(shù)組,找到其中的多數(shù)元素。多數(shù)元素是指在數(shù)組中出現(xiàn)次數(shù) 大于 ? n/2 ? 的元素。

你可以假設(shè)數(shù)組是非空的,并且給定的數(shù)組總是存在多數(shù)元素。

示例 1:

輸入:[3,2,3]
輸出:3

示例 2:

輸入:[2,2,1,1,1,2,2]
輸出:2

方法一:排序+取中間元素

public int majorityElement(int[] nums) {
    int n = nums.length;
    Arrays.sort(nums);
    return nums[n / 2];
}

方法二:HashMap
統(tǒng)計(jì)每個(gè)數(shù)字出現(xiàn)次數(shù),最后再做比較

方法三:摩爾投票

public int majorityElement(int[] nums) {
    int candidate = 0;
    int count = 0;
    for (int num : nums) {
        count += candidate == num ? 1 : -1;
        if (count < 0) {
            candidate = num;
            count = 1;
        }
    }
    return candidate;
}

摩爾投票法,解決的問(wèn)題是如何在任意多的候選人中,選出票數(shù)超過(guò)一半的那個(gè)人。注意,是超出一半票數(shù)的那個(gè)人。

假設(shè)投票是這樣的,[A, C, A, A, B],ABC 是指三個(gè)候選人。

第一張票與第二張票進(jìn)行對(duì)坑,如果票不同則互相抵消掉;
接著第三票與第四票進(jìn)行對(duì)坑,如果票相同,則增加這個(gè)候選人的可抵消票數(shù);
這個(gè)候選人拿著可抵消票數(shù)與第五張票對(duì)坑,如果票不同,則互相抵消掉,即候選人的可抵消票數(shù) -1。
但這不意味著這個(gè)候選人的票數(shù)一定能超過(guò)一半,例如 [A, B, C] 的抵消階段,最后得到的結(jié)果是 [C,1],C 候選人的票數(shù)也未能超過(guò)一半的票數(shù)。

在這里發(fā)現(xiàn)了一個(gè)優(yōu)化,如果最后得到的可抵消票數(shù)是 0 的話,那他已經(jīng)無(wú)緣票數(shù)能超過(guò)一半的那個(gè)人了。因?yàn)楸緛?lái)可能有希望的,但是被后面的一張不同的票抵消掉了。所以,在這里可以直接返回結(jié)果,無(wú)需后面的計(jì)算了。
如果最后得到的抵消票數(shù)不為 0 的話,那說(shuō)明他可能希望的,這是我們需要一個(gè)階段來(lái)驗(yàn)證這個(gè)候選人的票數(shù)是否超過(guò)一半—— 計(jì)數(shù)階段。

所以摩爾投票法分為兩個(gè)階段:抵消階段和計(jì)數(shù)階段。
抵消階段:兩個(gè)不同投票進(jìn)行對(duì)坑,并且同時(shí)抵消掉各一張票,如果兩個(gè)投票相同,則累加可抵消的次數(shù);
計(jì)數(shù)階段:在抵消階段最后得到的抵消計(jì)數(shù)只要不為 0,那這個(gè)候選人是有可能超過(guò)一半的票數(shù)的,為了驗(yàn)證,則需要遍歷一次,統(tǒng)計(jì)票數(shù),才可確定。

摩爾投票法經(jīng)歷兩個(gè)階段最多消耗O(2n) 的時(shí)間,也屬于 O(n)的線性時(shí)間復(fù)雜度,另外空間復(fù)雜度也達(dá)到常量級(jí)。

為了和下一題統(tǒng)一寫(xiě)成:

public int majorityElement(int[] nums) {
    int candidate = nums[0];
    int vote = 0;
    for (int num : nums) {
        if (vote > 0 && num == candidate) {
            vote++;
        } else if (vote == 0) {
            candidate = num;
            vote = 1;
        } else {
            vote--;
        }
    }
    return candidate;
}

求眾數(shù) II

給定一個(gè)大小為 *n *的整數(shù)數(shù)組,找出其中所有出現(xiàn)超過(guò) ? n/3 ? 次的元素。

摩爾投票
題目可以看作是:在任意多的候選人中,選出票數(shù)超過(guò)? 1/3 ?的候選人。
我們可以這樣理解,假設(shè)投票是這樣的 [A, B, C, A, A, B, C],ABC 是指三個(gè)候選人。
第 1 張票,第 2 張票和第3張票進(jìn)行對(duì)坑,如果票都不同,則互相抵消掉;
第 4 張票,第 5 張票和第 6 張票進(jìn)行對(duì)坑,如果有部分相同,則累計(jì)增加他們的可抵消票數(shù),如 [A, 2] 和 [B, 1];
接著將 [A, 2] 和 [B, 1] 與第 7 張票進(jìn)行對(duì)坑,如果票都沒(méi)匹配上,則互相抵消掉,變成 [A, 1] 和 `[B, 0] 。

如果至多選一個(gè)代表,那他的票數(shù)至少要超過(guò)一半(? 1/2 ?)的票數(shù);
如果至多選兩個(gè)代表,那他們的票數(shù)至少要超過(guò) ? 1/3 ? 的票數(shù);
如果至多選m個(gè)代表,那他們的票數(shù)至少要超過(guò) ? 1/(m+1) ? 的票數(shù)。
所以以后碰到這樣的問(wèn)題,而且要求達(dá)到線性的時(shí)間復(fù)雜度以及常量級(jí)的空間復(fù)雜度,直接套上摩爾投票法。

public List<Integer> majorityElement(int[] nums) {
    // 投票階段
    int candidate1 = nums[0], candidate2 = nums[0];
    int vote1 = 0, vote2 = 0;
    for (int i = 0; i < nums.length; i++) {
        if (vote1 > 0 && nums[i] == candidate1) {
            vote1++;
        } else if (vote2 > 0 && nums[i] == candidate2) {
            vote2++;
        } else if (vote1 == 0) {
            candidate1 = nums[i];
            vote1 = 1;
        } else if (vote2 == 0) {
            candidate2 = nums[i];
            vote2 = 1;
        } else {
            vote1--;
            vote2--;
        }
    }
    // 計(jì)數(shù)階段
    int cnt1 = 0, cnt2 = 0;
    for (int num : nums) {
        if (num == candidate1) {
            cnt1++;
        } else if (num == candidate2) {
            cnt2++;
        }
    }
    // 判斷是否滿足條件
    List<Integer> res = new ArrayList<>();
    if (vote1 > 0 && cnt1 > nums.length / 3) {
        res.add(candidate1);
    }
    if (vote2 > 0 && cnt2 > nums.length / 3) {
        res.add(candidate2);
    }
    return res;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 給定一個(gè)大小為 n 的數(shù)組,找到其中的多數(shù)元素。多數(shù)元素是指在數(shù)組中出現(xiàn)次數(shù)大于 ? n/2 ? 的元素。你可以假...
    做夢(mèng)枯島醒閱讀 423評(píng)論 2 1
  • 題目描述 給定一個(gè)大小為 n 的數(shù)組,找到其中的多數(shù)元素。多數(shù)元素是指在數(shù)組中出現(xiàn)次數(shù)大于 ? n/2 ? 的元素...
    su945閱讀 191評(píng)論 0 0
  • 給定一個(gè)大小為 n 的數(shù)組,找到其中的多數(shù)元素。多數(shù)元素是指在數(shù)組中出現(xiàn)次數(shù)大于 ? n/2 ? 的元素。你可以假...
    Jachin111閱讀 187評(píng)論 0 0
  • 2020/3/15 題目描述 給定一個(gè)大小為 n 的數(shù)組,找到其中的多數(shù)元素。多數(shù)元素是指在數(shù)組中出現(xiàn)次數(shù)大于 ?...
    icespark閱讀 306評(píng)論 0 0
  • 給定一個(gè)大小為 n 的數(shù)組,找到其中的多數(shù)元素。多數(shù)元素是指在數(shù)組中出現(xiàn)次數(shù)大于 ? n/2 ? 的元素。你可以假...
    enjoy_coding閱讀 262評(píng)論 0 5

友情鏈接更多精彩內(nèi)容