四种解法剑指 Offer 39. 数组中出现次数超过一半的数字
Posted 来老铁干了这碗代码
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了四种解法剑指 Offer 39. 数组中出现次数超过一半的数字相关的知识,希望对你有一定的参考价值。
立志用最少的代码做最高效的表达
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。
示例 1:
输入: [1, 2, 3, 2, 2, 2, 5, 4, 2]
输出: 2
限制:
1 <= 数组长度 <= 50000
代码一:HashMap
做法:利用hashmap统计次数,最后输出出现次数最多的变量
时间复杂度:O(n)
空间复杂度:O(n)
显而易见的缺点:没有利用“出现次数超过一半”这个条件
static class Solution1 {
public int maxCount(int[] nums) {
if(nums.length == 0) return -1;
Map<Integer, Integer> map = new HashMap<>();
int max = 0, max_value = -0x7fffffff, len = nums.length;
for(int i = 0; i < len; i++) {
if(map.putIfAbsent(nums[i],1) != null) // 如果为空,则赋值为0
map.put(nums[i], map.get(nums[i])+1);
if(max_value < map.get(nums[i])) { max_value = map.get(nums[i]); max = nums[i]; }
}
return max;
}
}
代码二:针对代码一的优化
针对思路一的优化:因为出现次数超过一半即可,因此无需遍历完整张表,当某个值出现次数超过一半,结束循环,输出即可。
时间复杂度:O(n/2)~O(n)
空间复杂度:O(n)
class Solution {
public int maxCount(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
int max = 0, max_value = -0x7fffffff, len = nums.length;
for(int i = 0; i < len; i++) {
if(map.putIfAbsent(nums[i],1) != null) // 如果为空,则赋值为0
map.put(nums[i], map.get(nums[i])+1);
if(map.get(nums[i]) > len/2)
return nums[i];
}
return -1;
}
}
代码三:排序算法
由于出现次数超过一半,因此排序后,数组的中间值一定为该数。
时间复杂度:O(nlogn)
空间复杂度:O(1)
class Solution3 {
public int maxCount(int[] nums) {
Arrays.sort(nums);
return nums[nums.length/2];
}
}
代码四:摩尔投票法
可以理解为同归于尽大法,一个对一个,最后活下来的一定是出现次数超过一半的
class Solution {
public int majorityElement(int[] nums) {
int res = 0, count = 0;
for(int i : nums)
if(count == 0) {
res = i; count++;
}
else
count += (res==i ? 1 : -1);
return res;
}
}
完整可运行Java代码
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
public class 剑指Offer39_数组中次数超一半的数字 {
// 1、hashmap:双O(n)
// 做法:利用hashmap统计次数,最后输出出现次数最多的变量
// 显而易见的缺点:没有利用“出现次数超过一半”这个条件
static class Solution1 {
public int maxCount(int[] nums) {
if(nums.length == 0) return -1;
Map<Integer, Integer> map = new HashMap<>();
int max = 0, max_value = -0x7fffffff, len = nums.length;
for(int i = 0; i < len; i++) {
if(map.putIfAbsent(nums[i],1) != null) // 如果为空,则赋值为0
map.put(nums[i], map.get(nums[i])+1);
if(max_value < map.get(nums[i])) { max_value = map.get(nums[i]); max = nums[i]; }
}
return max;
}
}
// 2、针对思路一的优化;因为出现次数超过一半即可,因此无需遍历完整张表,当某个值出现次数超过一半,结束循环,输出即可。
// 时间O(n/2),空间O(n)
static class Solution2 {
public int maxCount(int[] nums) {
Map<Integer, Integer> map = new HashMap<>();
int max = 0, max_value = -0x7fffffff, len = nums.length;
for(int i = 0; i < len; i++) {
if(map.putIfAbsent(nums[i],1) != null) // 如果为空,则赋值为0
map.put(nums[i], map.get(nums[i])+1);
if(map.get(nums[i]) > len/2)
return nums[i];
}
return -1;
}
}
// 3、排序:O(nlogn)、O(1)
static class Solution3 {
public int maxCount(int[] nums) {
Arrays.sort(nums);
return nums[nums.length/2];
}
}
// 4、摩尔投票法,可以理解为同归于尽大法,一个对一个,最后活下来的一定是出现次数超过一半的
static class Solution4 {
public int majorityElement(int[] nums) {
int res = 0, count = 0;
for(int i : nums)
if(count == 0) {
res = i; count++;
}
else
count += (res==i ? 1 : -1);
return res;
}
}
public static void main(String[] args) {
}
}
以上是关于四种解法剑指 Offer 39. 数组中出现次数超过一半的数字的主要内容,如果未能解决你的问题,请参考以下文章