[leetcode 双周赛 6] 1150 检查一个数是否在数组中占绝大多数
1150 Check If a Number Is Majority Element in a Sorted Array 检查一个数是否在数组中占绝大多数
描述
给出一个按 非递减 顺序排列的数组 nums
,和一个目标数值 target
。
假如数组 nums 中绝大多数元素的数值都等于 target,则返回 True,否则请返回 False。
所谓占绝大多数,是指在长度为 N 的数组中出现必须 超过 N/2
次。
- 示例 1:
输入:nums = [2,4,5,5,5,5,5,6,6], target = 5
输出:true
解释:
数字 5 出现了 5 次,而数组的长度为 9。
所以,5 在数组中占绝大多数,因为 5 次 > 9/2。
- 示例 2:
输入:nums = [10,100,101,101], target = 101
输出:false
解释:
数字 101 出现了 2 次,而数组的长度是 4。
所以,101 不是 数组占绝大多数的元素,因为 2 次 = 4/2。
- 提示:
1 <= nums.length <= 1000
1 <= nums[i] <= 10^9
1 <= target <= 10^9
思路
审题!!! 审题!!! 注意审题!!!
根据已知条件
来达到题目要求
- 已知条件
- 非递减 顺序排列的数组
- 占绝大多数的含义
- 目标数值
- 题目要求
目标数值在数组中的出现频次是否占绝大多数?
代码实现
暴力求取每个不重复元素的出现次数
class Solution {
/**
* 审题不清楚 求数组中出现频次最多的元素 -是否占绝大多数 -是否为目标数值
* 应该是 求数组中目标数值的出现次数 -是否大于N/2
* */
public boolean isMajorityElement(int[] nums, int target) {
if (nums.length == 0 | null == nums) return false;
if (nums.length == 1) return nums[0] == target;
// 通过set的特性获取数组中不重复元素
HashSet<Integer> set = new HashSet<>();
for (int i : nums) set.add(i);
// counts 每个不重复元素在数组中的出现频次
int[] counts = new int[set.size()];
// numSet 数组中不重复元素
int[] numSet = new int[set.size()];
// 遍历counts/numSet的指针
int index = 0;
// 遍历set集合
for (Integer inum : set) {
int count = 0;
// 获取元素在数组中出现频次
for (int i = 0; i < nums.length; i++) {
if (nums[i] == inum) count++;
}
counts[index] = count;
numSet[index] = inum;
index++;
}
int half = nums.length / 2;
// 找出数组中出现频次大于N/2 并且等目标数值的数据
for (int i = 0; i < set.size(); i++) {
if (counts[i] > half) return numSet[i] == target;
}
return false;
}
}
遍历筛选符合题意的数据
class Solution {
/**
* 符合题意的答案 求数组中目标数值的出现次数 -是否大于N/2
* */
public boolean isMajorityElement(int[] nums, int target) {
if (nums.length == 0 | null == nums) return false;
if (nums.length == 1) return nums[0] == target;
// 求目标数值在数组中出现次数
int count = 0;
for (int i : nums) if (i == target) count++;
// 出现频次是否大于N/2
return count*2 > nums.length;
}
}
二分查找符合题意的数据
class Solution {
/**
* 符合题意的答案 求数组中目标数值的出现次数 -是否大于N/2
* 并且用到了题目提供的条件 非递减 顺序排列的数组
* 可以使用二分查找的方法
* */
public boolean isMajorityElement(int[] nums, int target) {
if (nums.length == 0 | null == nums) return false;
if (nums.length == 1) return nums[0] == target;
// 通过找到目标数值在数组中的位置index
int count = 1, index = bs(nums, target);
if (index < 0) return false;
// 基于index 双向查找等于目标数值的元素
int i = index-1, j = index+1;
// --> 0 出现小于target的就中止
while (i >= 0 && nums[i--] >= target) count++;
// --> N 出现大于target的就中止
while (j < nums.length && nums[j++] <= target) count++;
return count*2 > nums.length;
}
/**
* 二分查找(迭代)
* */
int bs(int[] nums, int target) {
int begin = 0;
int end = nums.length - 1;
while(begin <= end) {
int mid = begin + (end - begin)/2;
if (target == nums[mid]) return mid;
else if (target < nums[mid]) end = mid-1;
else if (target > nums[mid]) begin = mid+1;
}
return -(begin+1);
}
}