Majority Number III

Question

  1. Given an array of integers and a number k,
  2. the majority number is the number that occurs more than 1/k of the size of the array.
  3. Find it.
  4. Example
  5. Given [3,1,2,3,2,3,3,4,4,4] and k=3, return 3.
  6. Note
  7. There is only one majority number in the array.
  8. Challenge
  9. O(n) time and O(k) extra space

题解

Majority Number II 的升级版,有了前两道题的铺垫,此题的思路已十分明了,对 K-1个数进行相互抵消,这里不太可能使用 key1, key2…等变量,用数组使用上不太方便,且增删效率不高,故使用哈希表较为合适,当哈希表的键值数等于 K 时即进行清理,当然更准备地来讲应该是等于 K-1时清理。故此题的逻辑即为:1. 更新哈希表,若遇哈希表 size == K 时则执行删除操作,最后遍历哈希表取真实计数器值,返回最大的 key.

C++

  1. class Solution {
  2. public:
  3. /**
  4. * @param nums: A list of integers
  5. * @param k: As described
  6. * @return: The majority number
  7. */
  8. int majorityNumber(vector<int> nums, int k) {
  9. unordered_map<int, int> map;
  10. for (auto n : nums) {
  11. if (map.size() < k) map[n]++;
  12. else {
  13. if (map.count(n)) map[n]++;
  14. else {
  15. map[n] = 1;
  16. vector<int> keys;
  17. for (auto &it : map) {
  18. it.second--;
  19. if (!it.second) keys.push_back(it.first);
  20. }
  21. for (int i : keys) map.erase(i);
  22. }
  23. }
  24. }
  25. int mx = 0;
  26. int ret = 0;
  27. for (auto &it : map) {
  28. if (it.second > mx) {
  29. ret = it.first;
  30. mx = it.second;
  31. }
  32. }
  33. return ret;
  34. }
  35. };

Java

  1. public class Solution {
  2. /**
  3. * @param nums: A list of integers
  4. * @param k: As described
  5. * @return: The majority number
  6. */
  7. public int majorityNumber(ArrayList<Integer> nums, int k) {
  8. HashMap<Integer, Integer> hash = new HashMap<Integer, Integer>();
  9. if (nums == null || nums.isEmpty()) return -1;
  10. // update HashMap
  11. for (int num : nums) {
  12. if (!hash.containsKey(num)) {
  13. hash.put(num, 1);
  14. if (hash.size() >= k) {
  15. removeZeroCount(hash);
  16. }
  17. } else {
  18. hash.put(num, hash.get(num) + 1);
  19. }
  20. }
  21. // reset
  22. for (int key : hash.keySet()) {
  23. hash.put(key, 0);
  24. }
  25. for (int key : nums) {
  26. if (hash.containsKey(key)) {
  27. hash.put(key, hash.get(key) + 1);
  28. }
  29. }
  30. // find max
  31. int maxKey = -1, maxCount = 0;
  32. for (int key : hash.keySet()) {
  33. if (hash.get(key) > maxCount) {
  34. maxKey = key;
  35. maxCount = hash.get(key);
  36. }
  37. }
  38. return maxKey;
  39. }
  40. private void removeZeroCount(HashMap<Integer, Integer> hash) {
  41. Set<Integer> keySet = hash.keySet();
  42. for (int key : keySet) {
  43. hash.put(key, hash.get(key) - 1);
  44. }
  45. /* solution 1 */
  46. Iterator<Map.Entry<Integer, Integer>> it = hash.entrySet().iterator();
  47. while (it.hasNext()) {
  48. Map.Entry<Integer, Integer> entry = it.next();
  49. if(entry.getValue() == 0) {
  50. it.remove();
  51. }
  52. }
  53. /* solution 2 */
  54. // List<Integer> removeList = new ArrayList<>();
  55. // for (int key : keySet) {
  56. // hash.put(key, hash.get(key) - 1);
  57. // if (hash.get(key) == 0) {
  58. // removeList.add(key);
  59. // }
  60. // }
  61. // for (Integer key : removeList) {
  62. // hash.remove(key);
  63. // }
  64. /* solution3 lambda expression for Java8 */
  65. }
  66. }

源码分析

此题的思路不算很难,但是实现起来还是有点难度的,Java 中删除哈希表时需要考虑线程安全。

复杂度分析

时间复杂度 O(n), 使用了哈希表,空间复杂度 O(k).

Reference