这一周的课程讲的是分治法,于是选一个分治法里面最简单来做,发现并没有使用到分治法的思想,尴尬→_→
1. 题目描述
Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.You may assume that the array is non-empty and the majority element always exist in the array.
2. 分析
题目描述简单的一清二楚,给个数组,然后输出其中的一个元素,这个元素在数组里面出现的次数大于⌊ n/2 ⌋次。
2.1. 解法1:利用map
拿到题目,最容易想到的解法就是利用Map:把原来的数组里面的元素映射到map里面,然后去计数每个元素出现的次数。map的第一个键值作为元素,第二个值作为在原数组中出现的个数。
具体做法是:我们开启一层循环,判断每一个原数组中出现的元素是否可以直接插入map,如果map中没出现,就把它作为键,将1次作为值,生成一个键值对插入进map。如果出现过该键,则该键对应的值加一,之后判断该值是否超过了⌊ n/2 ⌋,达到的话,直接返回该键,表明该键元素就是在原数组中出现次数超过了⌊ n/2 ⌋。
2.2. 解法2:观察
有点作弊的嫌疑哦,我们仔细思考一下,一个数组,如果里面有一个数字它出现的次数超过了⌊ n/2 ⌋,那么我们将数组排序就可以知道,⌊ n/2 ⌋的位置肯定就是这个元素了。原因很简单:无论该元素是数组中最大或者最小的元素,它在数组里面出现的次数都会保证⌊ n/2 ⌋的位置肯定是它。
2.3. 解法3:Moore Voting
看了讨论区大佬们的算法,觉得智商被碾压了。有一种很巧妙的算法:将Majority设为数组中第一个元素,设一个计数器从1开始接下来遍历:如果计数器为0则将当前数组元素设为Majority,否则,如果当前Majority与下一个元素相等,计数器加1,否则计数器减1。它的思想其实就是当Majority等于0的时候,目前数组中还没有重复次数能够超过一半的元素。
3. 源码
3.1. map方法代码
class Solution {
public:
int majorityElement(vector<int>& nums) {
map<int, int> hash;
int i;
for (i = 0; i < (int)nums.size(); i++) {
if (!hash.empty()) {
map<int, int>::iterator it = hash.find(nums[i]);
if (it == hash.end()) {
hash.insert(pair<int, int>(nums[i], 1));
}
else {
//根据键找到值,对值加一操作,表明出现的次数加一
int temp = (*it).second + 1;
hash.erase(nums[i]);
hash.insert(pair<int, int>(nums[i], temp));
if (temp > (int)(nums.size() / 2)) {
return nums[i];
}
}
}
else {
hash.insert(pair<int, int>(nums[i], 1));
}
}
return nums[0];
}
};
3.2. 观察方法,两行搞定
class Solution {
public:
int majorityElement(vector<int>& nums) {
sort(nums.begin(), nums.end());
return nums[nums.size()/2];
}
};
3.3. Moore Voting
class Solution {
public:
int majorityElement(vector<int>& nums) {
int counter = 1;
int i;
int majority = nums[0];
for (i = 1 ; i < (int)nums.size(); i++) {
if (counter == 0) {
counter++;
majority = nums[i];
}
else if (majority == nums[i]) {
counter ++;
}
else {
counter --;
}
}
return majority;
}
};
4. 心得
本来是练练分治法,没想到没用到分治法。不过后来看了大佬们的讨论,自己觉得其实Moore Voting也是利用了分治法的思想:在遍历中不断判断已检测的部分是否符合有元素出现次数超过一半,没有的话对数组剩下的部分执行相同操作,这勉强算作分治法的一个应用吧。