【leetcode】169. Majority Element
2016-06-05 20:00
253 查看
一、题目描述
Given an array of size n, find the majority element. The majority element is the element that appears more than
You may assume that the array is non-empty and the majority element always exist in the array.
题目解读:有一个序列长度为n,找出其中元素出现次数大于n/2次数的元素
思路:使用map,将序列中的每个元素与出现次数对应
自己写的c++代码(29ms)
class Solution {
public:
int majorityElement(vector<int>& nums) {
int len=nums.size();
map<int, int> count;
for(int i=0; i<len; i++){
if(++count[nums[i]] > len/2)
return nums[i];
}
return 0;
}
};
注意,在没有加最后的return 0时,运行会出现control reaches end of non-void function [-Werror=return-type] 这个错误,原因是编译器没有我们聪明,它担心如果所有的counts[nums[i]]都不大于n/2,即进不到if里面,那么这个函数就没有返回值了,所以报错。由题目可知,序列中肯定会存在一个元素出现的次数大于n/2,因此在for循环后任意加一个return值即可,对结果并不会产生什么影响。
其他代码:
使用nth_element(20ms)
思路:对序列进行排序,取出第nums.size()/2位置的元素。因为要求元素出现次数大于n/2,因此正中间位置的元素必为要求的元素。
class Solution {
public:
int majorityElement(vector<int>& nums) {
nth_element(nums.begin(), nums.begin() + nums.size() / 2, nums.end());
return nums[nums.size() / 2];
}
};
Randomization
思路:从序列中随机选择一个元素,并且遍历序列看该元素出现次数是否大于n/2
int rand(void);
产生的是伪随机数字,每次执行时时相同的;若要不同,用函数srand()初始化它
void srand(unsigned int seed);
用来设置rand()产生随机数时的随机数种子,参数seed必须是个整数,通常可以利用time(0)的返回值或NULL来当做seed。如果每次seed都设相同值,rand()所产生的随机数值每次都会一样。
代码:(16ms)
class Solution {
public:
int majorityElement(vector<int>& nums) {
int n = nums.size();
srand(unsigned(time(NULL)));
while (true) {
int idx = rand() % n;
int candidate = nums[idx];
int counts = 0;
for (int i = 0; i < n; i++)
if (nums[i] == candidate)
counts++;
if (counts > n / 2) return candidate;
}
}
};
Divide and Conquer
采用递归的思想,如果序列只有一个元素,那么这个元素就是所求
代码:(24ms)
class Solution {
public:
int majorityElement(vector<int>& nums) {
return majority(nums, 0, nums.size() - 1);
}
private:
int majority(vector<int>& nums, int left, int right) {
if (left == right) return nums[left];
int mid = left + ((right - left) >> 1);
int lm = majority(nums, left, mid);
int rm = majority(nums, mid + 1, right);
if (lm == rm) return lm;
return count(nums.begin() + left, nums.begin() + right + 1, lm) > count(nums.begin() + left, nums.begin() + right + 1, rm) ? lm : rm;
}
};
Moore Voting Algorithm
这个算法解决的问题:从一个数组中找出出现半数以上的元素。
基本思想:每次都找出一对不同的元素,从数组中删掉,直到数组为空或只有一种元素。不难证明,如果存在元素e出现频率超过半数,那么数组中最后剩下的就只有e。
算法实现:
(1)使用常量空间实时记录一个候选元素c以及其出现次数f(c),c为当前阶段出现次数超过半数的元素
(2)遍历前进行初始化,元素c为空,f(c)=0
(3)在遍历数组A时,如果f(c)为空,表示当前没有候选元素,即还未找到超过半数的元素。那么,如果超过半数的元素c存在,那么c在剩下的子数组中,出现次数也一定超过半数。因此我们可以将原始问题转化为它的子问题。此时c赋值为当前元素,同时f(c)=1
(4)如果当前元素A[i] == c,那么f(c)+=1.(没有找到不同元素,累计)
(5)如果当前元素A[i] != c,那么f(c) -= 1. 不对A[i]做任何处理。
(6)如果遍历结束之后,f(c)不为0,那么元素c即为寻找的元素。
算法的时间复杂度为O(n),因为不需要真的删除数组元素,我们并不需要额外的空间来保存原始数组,空间复杂度O(1).
代码:
class Solution {
public:
int majorityElement(vector<int>& nums) {
int major, counts = 0, n = nums.size();
for (int i = 0; i < n; i++) {
if (!counts) {
major = nums[i];
counts = 1;
}
else counts += (nums[i] == major) ? 1 : -1;
}
return major;
}
};
Bit Manipulation
思路:The key lies in how to count the number of
on a specific bit. Specifically, you need a
a
the
bit and
to get the
bit of each element in
class Solution {
public:
int majorityElement(vector<int>& nums) {
int major = 0, n = nums.size();
for (int i = 0, mask = 1; i < 32; i++, mask <<= 1) {
int bitCounts = 0;
for (int j = 0; j < n; j++) {
if (nums[j] & mask) bitCounts++;
if (bitCounts > n / 2) {
major |= mask;
break;
}
}
}
return major;
}
};
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.
题目解读:有一个序列长度为n,找出其中元素出现次数大于n/2次数的元素
思路:使用map,将序列中的每个元素与出现次数对应
自己写的c++代码(29ms)
class Solution {
public:
int majorityElement(vector<int>& nums) {
int len=nums.size();
map<int, int> count;
for(int i=0; i<len; i++){
if(++count[nums[i]] > len/2)
return nums[i];
}
return 0;
}
};
注意,在没有加最后的return 0时,运行会出现control reaches end of non-void function [-Werror=return-type] 这个错误,原因是编译器没有我们聪明,它担心如果所有的counts[nums[i]]都不大于n/2,即进不到if里面,那么这个函数就没有返回值了,所以报错。由题目可知,序列中肯定会存在一个元素出现的次数大于n/2,因此在for循环后任意加一个return值即可,对结果并不会产生什么影响。
其他代码:
使用nth_element(20ms)
思路:对序列进行排序,取出第nums.size()/2位置的元素。因为要求元素出现次数大于n/2,因此正中间位置的元素必为要求的元素。
class Solution {
public:
int majorityElement(vector<int>& nums) {
nth_element(nums.begin(), nums.begin() + nums.size() / 2, nums.end());
return nums[nums.size() / 2];
}
};
Randomization
思路:从序列中随机选择一个元素,并且遍历序列看该元素出现次数是否大于n/2
int rand(void);
产生的是伪随机数字,每次执行时时相同的;若要不同,用函数srand()初始化它
void srand(unsigned int seed);
用来设置rand()产生随机数时的随机数种子,参数seed必须是个整数,通常可以利用time(0)的返回值或NULL来当做seed。如果每次seed都设相同值,rand()所产生的随机数值每次都会一样。
代码:(16ms)
class Solution {
public:
int majorityElement(vector<int>& nums) {
int n = nums.size();
srand(unsigned(time(NULL)));
while (true) {
int idx = rand() % n;
int candidate = nums[idx];
int counts = 0;
for (int i = 0; i < n; i++)
if (nums[i] == candidate)
counts++;
if (counts > n / 2) return candidate;
}
}
};
Divide and Conquer
采用递归的思想,如果序列只有一个元素,那么这个元素就是所求
代码:(24ms)
class Solution {
public:
int majorityElement(vector<int>& nums) {
return majority(nums, 0, nums.size() - 1);
}
private:
int majority(vector<int>& nums, int left, int right) {
if (left == right) return nums[left];
int mid = left + ((right - left) >> 1);
int lm = majority(nums, left, mid);
int rm = majority(nums, mid + 1, right);
if (lm == rm) return lm;
return count(nums.begin() + left, nums.begin() + right + 1, lm) > count(nums.begin() + left, nums.begin() + right + 1, rm) ? lm : rm;
}
};
Moore Voting Algorithm
这个算法解决的问题:从一个数组中找出出现半数以上的元素。
基本思想:每次都找出一对不同的元素,从数组中删掉,直到数组为空或只有一种元素。不难证明,如果存在元素e出现频率超过半数,那么数组中最后剩下的就只有e。
算法实现:
(1)使用常量空间实时记录一个候选元素c以及其出现次数f(c),c为当前阶段出现次数超过半数的元素
(2)遍历前进行初始化,元素c为空,f(c)=0
(3)在遍历数组A时,如果f(c)为空,表示当前没有候选元素,即还未找到超过半数的元素。那么,如果超过半数的元素c存在,那么c在剩下的子数组中,出现次数也一定超过半数。因此我们可以将原始问题转化为它的子问题。此时c赋值为当前元素,同时f(c)=1
(4)如果当前元素A[i] == c,那么f(c)+=1.(没有找到不同元素,累计)
(5)如果当前元素A[i] != c,那么f(c) -= 1. 不对A[i]做任何处理。
(6)如果遍历结束之后,f(c)不为0,那么元素c即为寻找的元素。
算法的时间复杂度为O(n),因为不需要真的删除数组元素,我们并不需要额外的空间来保存原始数组,空间复杂度O(1).
代码:
class Solution {
public:
int majorityElement(vector<int>& nums) {
int major, counts = 0, n = nums.size();
for (int i = 0; i < n; i++) {
if (!counts) {
major = nums[i];
counts = 1;
}
else counts += (nums[i] == major) ? 1 : -1;
}
return major;
}
};
Bit Manipulation
思路:The key lies in how to count the number of
1's
on a specific bit. Specifically, you need a
maskwith
a
1on
the
i-the
bit and
0otherwise
to get the
i-th
bit of each element in
nums.
class Solution {
public:
int majorityElement(vector<int>& nums) {
int major = 0, n = nums.size();
for (int i = 0, mask = 1; i < 32; i++, mask <<= 1) {
int bitCounts = 0;
for (int j = 0; j < n; j++) {
if (nums[j] & mask) bitCounts++;
if (bitCounts > n / 2) {
major |= mask;
break;
}
}
}
return major;
}
};
相关文章推荐
- 强化学习-无模型控制(上)
- android上传图片压缩图片大小
- Git使用教程
- 关于WebHDFS与HttpFS
- javascript中闭包的概念
- Unity3d版FlappyBird(像素小鸟)
- 第十四周学习进度
- 设置控件获取焦点
- SQL SERVER 删除前先判断指定的表或者存储过程是否存在
- 结婚后谁管钱更高效?怎样越管越多?
- boost::function
- linux 系统调优2
- 单例模式
- C++第7次实验-项目1:素数和回文
- Android错误之--'keytool' 不是内部或外部命令,也不是可运行的程序
- 第十四周学习进度情况
- leetCode_Maximum Product Subarray
- 【Android】UI设计之界面布局
- Linux系统调优1
- 【Android 基础】android导入工程出现红色感叹号