今天分享的題目來源於 LeetCode 上第 169 號問題:求衆數(求數組中超過一半的數字)。題目難度爲 Easy,目前經過率爲 45.8% 。數組
最後一種解法 Cool !!!優化
給定一個大小爲 n 的數組,找到其中的衆數。衆數是指在數組中出現次數大於 ⌊ n/2 ⌋ 的元素。動畫
你能夠假設數組是非空的,而且給定的數組老是存在衆數。spa
示例 1:code
輸入: [3,2,3]
輸出: 3複製代碼
示例 2:blog
輸入: [2,2,1,1,1,2,2]
輸出: 2複製代碼
題目意思很好理解:給你一個數組,裏面有一個數字出現的次數超過了一半,你要找到這個數字並返回。ip
遍歷整個數組,同時統計每一個數字出現的次數。get
最後將出現次數大於一半的元素返回便可。it
class Solution {
public int majorityElement(int[] nums) {
int majorityCount = nums.length/2;
for (int num : nums) {
int count = 0;
for (int elem : nums) {
if (elem == num) {
count += 1;
}
}
if (count > majorityCount) {
return num;
}
}
}
}複製代碼
時間複雜度:O(n2)io
暴力解法包含兩重嵌套的 for 循環,每一層 n 次迭代,所以時間複雜度爲 O(n2) 。
空間複雜度:O(1)
暴力解法沒有分配任何與輸入規模成比例的額外的空間,所以空間複雜度爲 O(1)。
這個問題能夠視爲查找問題,對於查找問題每每可使用時間複雜度爲 O(1) 的 哈希表,經過以空間換時間的方式進行優化。
直接遍歷整個 數組 ,將每個數字(num)與它出現的次數(count)存放在 哈希表 中,同時判斷該數字出現次數是不是最大的,動態更新 maxCount,最後輸出 maxNum。
class Solution {
public int majorityElement(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
// maxNum 表示元素,maxCount 表示元素出現的次數
int maxNum = 0, maxCount = 0;
for (int num: nums) {
int count = map.getOrDefault(num, 0) + 1;
map.put(num, count);
if (count > maxCount) {
maxCount = count;
maxNum = num;
}
}
return maxNum;
}
}複製代碼
時間複雜度:O(n)
總共有一個循環,裏面哈希表的插入是常數時間的,所以時間複雜度爲 O(n)。
空間複雜度:O(n)
哈希表佔用了額外的空間 O(n),所以空間複雜度爲 O(n)。
再來回顧一下題目:尋找數組中超過一半的數字,這意味着數組中其餘數字出現次數的總和都是比不上這個數字出現的次數 。
即若是把 該衆數記爲 +1
,把其餘數記爲 −1
,將它們所有加起來,和是大於 0 的。
因此能夠這樣操做:
class Solution {
public int majorityElement(int[] nums) {
int candidate = nums[0], count = 1;
for (int i = 1; i < nums.length; ++i) {
if (count == 0) {
candidate = nums[i];
count = 1;
} else if (nums[i] == candidate) {
count++;
} else{
count--;
}
}
return candidate;
}
}複製代碼
時間複雜度:O(n)
總共只有一個循環,所以時間複雜度爲 O(n)。
空間複雜度:O(1)
只須要常數級別的額外空間,所以空間複雜度爲 O(1)。