剑指 Offer 39.数组中出现次数超过一半的数字
剑指 Offer 39.数组中出现次数超过一半的数字
给定一个大小为 n 的数组 nums ,返回其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入:nums = [3,2,3]
输出:3
示例 2:
输入:nums = [2,2,1,1,1,2,2]
输出:2
提示:
n == nums.length
1 <= n <= 5 * 104
-109 <= nums[i] <= 109
进阶:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。
思路一
将数组进行排序,中间那个元素,就是所要找的值
本题使用插入排序
数据结构与算法—排序—插入排序、二分搜索
class Solution {
public int majorityElement(int[] nums) {
//边界条件
if(nums == null) return 0;
if(nums.length == 1) return nums[0];
insertSort(nums);
//或者使用系统自带排序算法
//Arrays.sort(nums);
int middleIndex = nums.length/2;
int result = nums[middleIndex];
return result;
}
//插入排序
public static void insertSort(int[] nums) {
if(nums == null) return;
for (int preInsertIndex = 1; preInsertIndex < nums.length; preInsertIndex++)
{
int saveValue = nums[preInsertIndex];
for(int sortedIndex = preInsertIndex; sortedIndex > 0; sortedIndex--){
if(nums[sortedIndex - 1] > saveValue){
nums[sortedIndex] = nums[sortedIndex - 1];
}else{
nums[sortedIndex] = saveValue;
break;
}
if(sortedIndex == 1){
nums[0] = saveValue;
}
}
}
}
}
思路二
运用哈希表,将每个元素的值放入哈希表中,如果继续增加,则+1,同时记录最大值,以及最大元素
参考:
数据结构与算法—在一个数组中找出相同个数最多的数
以上两种做法,都不能做到:尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。
查看解题后,发现有一种新的解法:
思路三
摩尔投票
前提是一定有半数以上的值是一样的
设输入数组 nums 的众数为 x ,数组长度为 n 。
- 推论一: 若记 众数 的票数为 +1,非众数 的票数为 −1,则一定有所有数字的 票数和 >0。
- 推论二: 若数组的前 a 个数字的 票数和 =0,则 数组剩余 (n−a) 个数字的 票数和一定仍 >0 ,即后 (n−a)个数字的 众数仍为 x。
举个栗子:
[7, 7, 5, 7, 5, 1 | 5, 7 | 5, 5, 7, 7 | 7, 7, 7, 7]
在遍历到数组中的第一个元素以及每个在 | 之后的元素时,candidate 都会因为 count 的值变为 0 而发生改变。最后一次 candidate 的值从 5 变为 7,也就是这个数组中的众数。
假设我们设置出现次数最多的值是moreValue,初始化从0开始,也就是nums[0]假设是我们寻找的结果值
我们维护一个候选众数 moreValue 和正负数相加的值:plusValue。初始时 moreValue 可以为任意值,plusValue 为 0;文章来源:https://www.toymoban.com/news/detail-812598.html
我们遍历数组 nums 中的所有元素,对于每个元素 x,在判断 x 之前,如果 plusValue 的值为 0,我们先将 x 的值赋予 moreValue,随后我们判断 x:
如果 x 与 moreValue 相等,那么计数器 plusValue 的值增加 1;
如果 x 与 moreValue 不等,那么计数器 plusValue 的值减少 1。
在遍历完成后,moreValue 即为整个数组的众数。文章来源地址https://www.toymoban.com/news/detail-812598.html
class Solution {
public int majorityElement(int[] nums) {
//边界条件
if(nums == null || nums.length == 0) return 0;
if(nums.length == 1) return nums[0];
//假设最多的数值是moreValue
int moreValue = 0;
//假设加起来的值是plusValue
int plusValue = 0;
for(int i = 0; i < nums.length; i++){
//如果加起来的值等于0了,新的值作为最多值
if(plusValue == 0){
moreValue = nums[i];
}
//如果假设的新的值,与新的比较值相等
if(nums[i] == moreValue){
//+1
plusValue++;
}else{
//-1
plusValue--;
}
}
//返回结果
return moreValue;
}
}
到了这里,关于剑指 Offer 39.数组中出现次数超过一半的数字的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!