题解 | #剑指offer28 出现次数超过一半的元素#
数组中出现次数超过一半的数字
https://www.nowcoder.com/practice/e8a1b01a2df14cb2b228b30ee6a92163?tpId=13&&tqId=11181&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking
剑指offer28 出现次数超过一半的元素
3、位运算方法实现
class Solution {
public:
//位运算实现:时间复杂度O(n*max) 空间复杂度O(1) max为数据类型长度,这里是int(32位为32):
//目标:找到出现次数最多的数据,并判断该数据出现次数是否超过一半
//分析:以32位int类型为例,出现次数超过一半的元素,它每一位的状态出现都是超过一半的
//如:5是出现最多元素,5=0101,则所有元素 第一位出现最多情况是1 第二位最多情况是0 第三位最多情况是1..依次类推32位
//又因为每一位非0即1,所以若1出现超过一半,0出现肯定少于一半,最多元素此位为1;若1出现次数少于一半,则最多元素此位为0
int MoreThanHalfNum_Solution(vector<int> numbers) {
if(numbers.size()==1) return numbers[0];
int ret=0; //最多元素,初始所有位均为0,然后不断判断每一位具体是多少,加入
int mask=1; //判断位辅助
int len=numbers.size();
for(int i=0;i<8*sizeof(int);i++) //sizeof(int)=int字节数,1字节=8位
{
int count=0; //记录某位1出现次数
for(int j=0;j<len;j++)
{
if((numbers[j]&mask)!=0)
++count;
}
if(count==(len-count)) //1等于一半,0等于一半,显然这组数据中没出现超过一半的元素提前剪枝
return -1;
if(count>(len-count)) //1超过一半,出现次数超过一半的元素可能存在,最后求出后再检查
{
ret|=mask; //ret的此位 状态为1 0超过一半状态为0,已默认不需要处理 这里用异或^ 和 或| 都行
}
mask<<=1; //左移1
}
int num=0;
for(int x:numbers) //检查求得元素是否出现次数超过一半,若不是,则不存在出现次数超过一半的元素
{
if(x==ret)
++num;
}
if(num>len/2)
return ret;
else
return -1;
}
};
4、摩尔投票法实现
class Solution {
public:
/*
摩尔投票法:
元素两两对抗相消,最后剩下的元素一定是出现超过一半的元素。最后检查剩下的那个元素出现的次数是否超过一半,
若超过为最终结果;若不超过,该数组中没有出现次数超过一半元素。
count:表示当前候选人数量(对抗相消后活下来的)
cand: 当前候选人(元素)
N:当前候选人全部死亡(全部相消了count=0)
相消规则:候选人x=num[k],若下一个元素与候选人相同,候选人不变,count+1;若不同,count-1,
若count=0候选人x=N,即此时无候选人,等到下一个元素Z来临重新开始,Z为候选人,count=1
*/
int MoreThanHalfNum_Solution(vector<int> numbers) {
//摩尔投票法
int cand=numbers[0]; //候选人,开始为第一个元素
int count=1;//当前相消后候选人数量,开始候选人1个
int len=numbers.size();
for(int i=1;i<len;i++)
{
if(count==0) //候选人为空,此时count==0,cand=INT_MAX,
{
cand=numbers[i];//候选人为空时,下一个元素无论是啥都是候选人,候选人数量置1即count=1
count=1;
}
else if(cand==numbers[i]) //候选人不为空,且和下一位相同
++count;
else //候选人不为空,且和下一位不同
{
--count;
if(count==0)//候选人为空,设置一个取不到的数(一般可以取最大值)
cand=INT_MAX; //其实改不改不重要,因为count=0也表示候选人为空,二者同时存在
}
}
int num=0;
for(int i=0;i<len;i++) //检查超过一半的元素是否存在,若存在就是cand,所以检查cand是否符合即可
{
if(cand==numbers[i])
++num;
}
if(num>len/2) //存在,cand符合
return cand;
else //不存在,返回-1
return -1;
}
};
CVTE公司福利 731人发布