剑指Offer 39 - 数组中出现次数超过一半的数
Posted xintangchn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指Offer 39 - 数组中出现次数超过一半的数相关的知识,希望对你有一定的参考价值。
力扣链接:https://leetcode-cn.com/problems/shu-zu-zhong-chu-xian-ci-shu-chao-guo-yi-ban-de-shu-zi-lcof/
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。你可以假设数组是非空的,并且给定的数组总是存在多数元素。
(以下“众数”特指出现次数超过数组长度一半的数)
思路一:摩尔投票法
基本思路是不断缩小众数所在的范围。假设数A为众数,遍历数组进行“投票”,是A则votes++,不是A则votes--,则当votes为0时,众数必然也是剩余数组中的众数。然后重新选择一个数假定为众数,循环该过程。可以一直将该过程进行到数组末尾的那个数为整个数组真正的众数。
代码:
/** * @param {number[]} nums * @return {number} */ var majorityElement = function(nums) { let votes = 0; let candidate; for(let i = 0; i < nums.length; i++){ if(votes === 0){ candidate = nums[i]; } if(nums[i] === candidate){ votes++; }else{ votes--; } } return candidate; };
时间复杂度:O(N)
空间复杂度: O(1)
思路二
排序,数组正中间的数一定是众数。
代码:(快速排序)
/** * @param {number[]} nums * @return {number} */ var majorityElement = function(nums) { quickSort(nums, 0, nums.length-1); return nums[parseInt(nums.length/2)]; }; function quickSort(nums, start, end){ if(start >= end) return; let left = start+1, right = end; let pivot = nums[start]; while(left < right){ while(nums[left] <= pivot) left++; while(nums[right] > pivot) right--; if(left >= right) break; swap(nums, left, right); } swap(nums, start, right); quickSort(nums, start, right - 1); quickSort(nums, right + 1, end); } function swap(nums, a, b){ const tmp = nums[a]; nums[a] = nums[b]; nums[b] = tmp; }
时间复杂度:O(NlogN)
空间复杂度:O(1)
思路三
一边遍历数组,一边统计每个数出现次数,记录在Map中。
代码:
/** * @param {number[]} nums * @return {number} */ var majorityElement = function(nums) { const map = new Map(); for(let num of nums){ if(map.has(num)){ map.set(num, map.get(num)+1); }else{ map.set(num, 1); } } for(let key of map.keys()){ if(map.get(key) > nums.length/2) return key; } };
时间复杂度:O(Nl)
空间复杂度:O(1)
以上是关于剑指Offer 39 - 数组中出现次数超过一半的数的主要内容,如果未能解决你的问题,请参考以下文章
剑指 Offer 39. 数组中出现次数超过一半的数字 的 详细题解
Java 剑指offer(39) 数组中出现次数超过一半的数字