1. 程式人生 > >LeetCode---169.求眾數

LeetCode---169.求眾數

題目來源:https://leetcode-cn.com/problems/majority-element/description/

題目描述:

演算法描述:對於該題目,可能有些人想到的就是最暴力的窮舉,但是時間複雜度為O(n2)。所以我們不用那種方法。我們可以可以使用分治演算法實現也可以用摩爾投票法。

第一種.分治演算法實現:

分治法是將整個問題化簡為一個一個的小問題去解,將陣列分成簡單的幾部分,比如講一組數分為兩部分,第一部分的眾數如果等於第二部分的眾數,則這個數就是上一層那一組的眾數,如果第一部分不等於第二部分,則遍歷這一組數,比較第一部分的眾數和第二部分的眾數哪個出現頻率高,頻率高的這個數就是這一組數的眾數。

程式碼如下:

class Solution {
	public int majorityElement(int[] nums) {
		return find(nums, 0, nums.length - 1);
	}

	public static int find(int[] nums, int begin, int end) {
		if (begin == end || begin + 1 == end)
			return nums[begin];
		else {
			//這裡主要是為了把陣列一分為二(這裡就體現了分治演算法的思想)
			int mid = (begin + end) / 2;
			//leftNum就是一個數組中,左半部分的眾數
			int leftNum = find(nums, begin, mid);
			//rightNum就是一個數組中,左半部分的眾數
			int rightNum = find(nums, mid + 1, end);
			// 左右兩部分的眾數相同 則這個數是當前這個陣列的眾數
			if (leftNum == rightNum) {
				return leftNum;
			}else {
				// 左右兩部分的眾數不相同 則這兩個數都有可能是這部分的眾數
				// 那麼遍歷這個陣列 看一下哪個數字的出現頻率高,頻率高的為當前這個陣列的眾數
				int countLeft = 0;
				int countRight = 0;
				for (int i = begin; i <= end; i++)
					if (nums[i] == leftNum)
						countLeft++;
					else if (nums[i] == rightNum)
						countRight++;

				if (countLeft > countRight)
					return leftNum;
				else
					return rightNum;
			}
		}
	}
}

第二種.摩爾投票法實現:

摩爾投票法的基本思想很簡單,在每一輪投票過程中,從陣列中找出一對不同的元素,將其從陣列中刪除。這樣不斷的刪除直到無法再進行投票,如果陣列為空,則沒有任何元素出現的次數超過該陣列長度的一半。如果只存在一種元素,那麼這個元素則可能為目標元素。那麼有沒有可能出現最後有兩種或兩種以上元素呢?根據定義,這是不可能的,因為如果出現這種情況,則代表我們可以繼續一輪投票。因此,最終只能是剩下零個或一個元素。

程式碼如下:

class Solution {
	public int majorityElement(int[] nums) {
		int result = nums[0], count = 0;
		for (int num : nums) {
			if (count == 0) {
				result = num;
				count++;
			} else {
				if (result == num) {
					count++;
				} else {
					count--;
				}
			}
		}
		return result;
	}
}