标签:
在一个数组中找到主要的元素,也就是出现次数大于数组长度一半的元素。
我想到的方法是
1. 排序,然后扫描一次就知道了。总共nlgn
2. 哈希,记录每个次数,O(n)的时间和空间。
class Solution { public: int majorityElement(vector<int> &num) { unordered_map<int, int> umap; for (int i = 0; i < num.size(); i++) { umap[num[i]]++; } for (unordered_map<int, int>::iterator itr = umap.begin(); itr != umap.end(); itr++) { if (itr -> second > num.size()/2) return itr -> first; } } };
再介绍两个O(n)时间O(1)空间的方法:
1. 投票算法,因为符合的众数总是存在。所以没出现一对不一样的就可以忽视这一对。我们可以用计数表示,来一个数字,如果和candidate相同那么count++,否则count--,如果count为零了,那么candidate就是下一个数。最后candidate就是众数了。
class Solution { public: int majorityElement(vector<int> &num) { int nTimes = 0; int candidate = 0; for(int i = 0; i < num.size(); i ++) { if(nTimes == 0) { candidate = num[i]; nTimes = 1; } else { if(candidate == num[i]) nTimes ++; else nTimes --; } } return candidate; } };
2. 因为给定的是32位数,并且众数一定存在,那么每一位去考虑的话,对于每一位1或者0多的肯定是属于众数的。这样就知道众数了。
class Solution { public: int majorityElement(vector<int> &num) { int bitCnt[32]; memset(bitCnt, 0, sizeof(bitCnt)); for (int i = 0; i < num.size(); i++) { for (int j = 0; j < 32; j++) { if (num[i] & (1 << j)) bitCnt[j]++; } } int ans = 0; for (int i = 0; i < 32; i++) { if (bitCnt[i] > num.size()/2) ans += (int)pow(2, i); } return ans; } };
再附上官方的解法和网友的翻译:
时间复杂度: O(n2) — 蛮力法: 依次检查每一个元素是否为众数
时间复杂度: O(n), 空间复杂度: O(n) — 哈希表: 维护一个每一个元素出现次数的哈希表, 然后找到出现次数最多的元素
时间复杂度: O(n log n) — 排序: 在排序后找出连续重复出现次数最多的元素
平均时间复杂度: O(n), 最坏复杂度: 无穷大 — 随机算法: 随机选取一个元素计算其是否为众数. 如果不是, 就重复上一步骤直到找到为止。 由于选出众数的概率 > 1 / 2, 因此期望的尝试次数 < 2
时间复杂度: O(n log n) — 分治法: 将数组拆成2半, 然后找出前一半的众数A和后一半的众数B。则全局众数要么是A要么是B。 如果 A == B, 则它自然而然就是全局众数。 如果不是, 则A和B都是候选汇众数, 则至多只需要检查这两个元素的出现次数即可。 时间复杂度, T(n) = T(n/2) + 2n = O(n log n).
时间复杂度: O(n) — Moore投票算法: 我们维护一个当前的候选众数和一个初始为0的计数器。遍历数组时,我们看当前的元素x:
如果计数器是0, 我们将候选众数置为 x 并将计数器置为 1
如果计数器非0, 我们根据x与当前的候选众数是否相等对计数器+1或者-1
一趟之后, 当前的候选众数就是所求众数. 时间复杂度 = O(n).
时间复杂度: O(n) — 位操作法: 我们需要32次迭代, 每一次计算所有n个数的第i位的1的个数。由于众数一定存在,那么或者1的个数 > 0的个数 或者反过来(但绝不会相同)。 众数的第i位一定是计数较多数字。
leetcode[169] Majority Element
标签:
原文地址:http://www.cnblogs.com/higerzhang/p/4181421.html