【剑指offer】【其他算法】39.数组中出现次数超过一半的数字
题目链接:https://leetcode-cn.com/problems/shu-zu-zhong-chu-xian-ci-shu-chao-guo-yi-ban-de-shu-zi-lcof/
循环抵消
因为数组中有一个数字出现的次数超过数组长度的一半,它出现的次数比所有其它数字出现的次数和还要多;
所以在遍历数组的时候,保存两个变量,次数和值,当遍历到一个数字:
1. 如果它与前一个数相同那么次数加1;
2. 如果不同,次数减1;
如果次数为0,那么需要保存的数下一个数,并把次数设置为1;
统计数字出现的个数cnt = 0, val = -1;
遍历数组中每个数字x
如果val = x, cnt++
如果val != x,
1. cnt != 0, cnt--;
2. cnt == 0, 更新val和cnt
时间复杂度O(N) 空间复杂度O(1)
class Solution {
public:
int majorityElement(vector<int>& nums) {
int res = nums[0], cnt = 1;
for(int i = 1; i < nums.size(); i++)
{
int x = nums[i];
if(res != x)
{
if(cnt) cnt--;
else
{
res = x;
cnt = 1;
}
}else
cnt++;
}
return res;
}
};
快排的思想
如果数组排好序的话,出现最多的那个数就是这个数组的中位数
快速排序每次都是在数组中随机选择一个数字,然后调整数字的顺序,使得它左边的数都比它小,右边的数都比他大;
我们每次也从中随机选一个数,把它放到合适的位置;
1. 如果它的下标刚好等于n/2,那么这个数字是数组的中位数;
2. 如果它的下标刚好大于n/2, 那么中位数在它的左边;我们接着在它的左边找
3. 如果它的下标刚好小于n/2, 那么中位数在它的右边;我们接着在它的右边找
/*
有问题
class Solution {
public:
int majorityElement(vector<int>& nums) {
int n = nums.size() - 1;
int s = 0, e = n;
int cur = partition(nums, s, e);
int mid = n >> 1;
while(cur != mid)
{
if(cur > mid)
{
e = cur - 1;
cur = partition(nums, s, e);
}
else
{
s = cur + 1;
cur = partition(nums, s, e);
}
}
return nums[cur];
// return 0;
}
int partition(vector<int>& nums, int l, int r)
{
if(l >= r) return -1;
int x = nums[(l + r) >> 1];
int i = l - 1, j = r + 1;
while(i < j)
{
do i++; while(nums[i] < x);
do j--; while(nums[j] > x);
if(i < j) swap(nums[i], nums[j]), cout<< nums[i] << " " << nums[j] << "hello" << endl;
}
for(int i = l; i < r - l + 1; i++)
cout << nums[i] << " ";
cout << endl;
cout << j << endl;
return j;
}
};
*/
知识的价值不在于占有,而在于使用