【LeetCode題解】169_求衆數(Majority-Element)

169_求衆數(Majority-Element)

這道題有 5 種方法,8 種實現,詳細分析能夠看<u>花花醬</u>的 YouTube 專欄java

[TOC]python

描述

給定一個大小爲 n 的數組,找到其中的衆數。衆數是指在數組中出現次數大於 ⌊ n/2 ⌋ 的元素。算法

你能夠假設數組是非空的,而且給定的數組老是存在衆數。數組

示例 1:ide

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

示例 2:spa

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

解法一:暴力法

思路

遍歷數組中的每一個元素,統計該元素出現的次數(嵌套遍歷),若是該元素出現的次數 $> \left \lfloor n/2 \right \rfloor$,則該元素就是數組的衆數。code

Java 實現

class Solution {
    public int majorityElement(int[] nums) {
        int majorityCount = nums.length / 2;
        for (int num1 : nums) {
            int count = 0;
            for (int num2 : nums) {
                if (num2 == num1) {
                    ++count;
                }
            }
            if (count > majorityCount) {
                return num1;
            }
        }
        throw new IllegalArgumentException("The array does not contain a majority element!");
    }
}

Python 實現

class Solution:
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        majority_count = len(nums) // 2
        for num1 in nums:
            count = sum(1 for num2 in nums if num2 == num1)
            if count > majority_count:
                return num1

複雜度分析

  • 時間複雜度:$O(n^2)$,其中 $n$ 表示數組的長度,因爲嵌套了兩層 for 循環,所以總的時間複雜度是 $O(n^2)$ 的
  • 空間複雜度:$O(1)$

解法二:哈希表

思路

利用哈希表記錄數組中元素出現的次數,因爲哈希表的插入操做的時間複雜度是 $O(1)$ 的,因此遍歷整個數組統計出現次數的操做的時間複雜度是 $O(n)$ 的。接着,再遍歷一遍哈希表,取出衆數。blog

Java 實現

class Solution {
    public int majorityElement(int[] nums) {
        Map<Integer, Integer> counts = new HashMap<>();
        for (int num : nums) {
            if (counts.containsKey(num)) {
                counts.replace(num, counts.get(num) + 1);
            } else {
                counts.put(num, 1);
            }
        }
        
        Map.Entry<Integer, Integer> majorityEntry = null;
        for (Map.Entry<Integer, Integer> entry : counts.entrySet()) {
            if (majorityEntry == null || entry.getValue() > majorityEntry.getValue()) {
                majorityEntry = entry;
            }
        }
        
        return majorityEntry.getKey();
    }
}

Python 實現

class Solution:
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        counts = dict()
        for num in nums:
            counts[num] = counts.get(num, 0) + 1
		return max(counts, key=counts.get)

複雜度分析

  • 時間複雜度:$O(n)$,其中 $n$ 爲數組的長度。因爲哈希表中元素的數目最多爲 $n - \left( \left \lfloor n/2 \right \rfloor + 1 \right) + 1 = n - \left \lfloor n/2 \right \rfloor$,所以遍歷一次哈希表最多須要 $n - \left \lfloor n/2 \right \rfloor$ 次操做,而遍歷一遍數組須要 $n$ 次操做,因此總的時間複雜度是 $O(n)$ 的
  • 空間複雜度:$O(n)$,由於哈希表最多須要保存 $n - \left \lfloor n/2 \right \rfloor$ 個元素

解法三:排序

將數組按照順序(遞增或者遞減)排列好後,索引爲 $\left \lfloor n/2 \right \rfloor$ 的元素就是數組的衆數。排序

Java 實現

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

Python 實現

class Solution:
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        return sorted(nums)[len(nums) // 2]

複雜度分析

  • 時間複雜度:$O(n \log(n))$,其中 $n$ 表示數組的長度,對數組進行排序的時間複雜度爲 $O(n \log(n))$ 的
  • 空間複雜度:$O(n)$ 或者 $O(1)$,取決因而否能夠直接對原數組直接進行排序,若是不容許的話,須要額外的空間複製數組

解法四:隨機選擇【待完成】

思路

Java實現

Python 實現

複雜度分析

解法五:分而治之(Divide and conquer)【待完成】

思路

Java 實現

Python 實現

複雜度分析

解法六:多數投票算法(Boyer-Moore majority vote algorithm)

思路

多數投票算法通常用於尋找一個序列的多數元素(只須要線性時間和常數空間),是一種典型的流式算法(streaming algorithm)。可是,通常來講,該算法沒法找到一個序列的衆數(mode),除非衆數出現的次數大於 $\lfloor n/2 \rfloor$ 次。多數投票算法的思想是這樣:統計一個序列中的全部元素,將多數元素記爲 $+1$,其他的元素記爲 $-1$,那麼最後的和必定是正的。具體地,該算法會維護兩個變量,一個用於記錄序列中的元素,記爲 m,一個做爲計數器,記爲 count。遍歷數組中的每一個元素,若是當前的 count 爲 0,則將當前元素保存在 m 中,並設 count 爲1;若是 count 不爲0,則判斷當前元素與 m 是否相等,相等則 count 加一,不等則 count 減一。遍歷結束,變量 m 就是咱們尋找的多數元素。索引

Java 實現

class Solution {
    public int majorityElement(int[] nums) {
        int me = nums[0], count = 1;
        for (int i = 1; i < nums.length; ++i) {
            if (count == 0) {
                me = nums[i];
                count = 1;
            } else if (me == nums[i]) {
                ++count;
            } else {
                --count;
            }
        }
        return me;
    }
}

Python 實現

class Solution:
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        me, count = 0, 0
        for num in nums:
            if count == 0:
                me, count = num, 1
            elif me == num:
                count += 1
            else:
                count -= 1
        return me

複雜度分析

  • 時間複雜度:$O(n)$,其中 $n$ 表示數組的長度
  • 空間複雜度:$O(1)$
相關文章
相關標籤/搜索