题意:
- 多数:数组中出现次数大于 n 2 \frac{n}{2} 2n 的数
- 输入一个含有多数元素的数组
- 找出该多数
解法1 (暴力法)
思路:
- 找出数组中每一个元素出现的次数
- 次数保存在一个相同长度的数组中
- 遍历该数组找出最大值的下标即为多数的下标
class Solution {
public int majorityElement(int[] nums) {
int[] helper = new int[nums.length];
int count = 0;
for (int i = 0; i < nums.length; i++) {
count = 0;
for (int j = 0; j < nums.length; j++) {
if (nums[j] == nums[i]) {
count++;
}
}
helper[i] = count;
}
int max = helper[0];
int maxOfIndex = 0;
for (int i = 0; i < helper.length; i++) {
if (helper[i] > max) {
max = helper[i];
maxOfIndex = i;
}
}
return nums[maxOfIndex];
}
}
解法2(哈希映射)
思路:
- 将数组中不同的元素和其出现的次数映射到哈希表中
- 将哈希表转为Set集合,找出value值最大的entry
- 返回其key值即多数
class Solution {
public int majorityElement(int[] nums) {
HashMap<Integer, Integer> map = new HashMap<>();
// 将数组中不同元素的出现次数以键值对的方式映射到map中
for (int num : nums) {
if (map.containsKey(num)) {
map.put(num, map.get(num) + 1);
} else {
map.put(num, 1);
}
}
Set<Map.Entry<Integer, Integer>> set = map.entrySet();
// 找出value值(出现次数)最大的entry
int max = 0;
Map.Entry<Integer, Integer> maxEntry = null;
for (Map.Entry<Integer, Integer> entry : set) {
if (entry.getValue() > max) {
max = entry.getValue();
maxEntry = entry;
}
}
return maxEntry.getKey();
}
}
解法3(排序后返回中值)
思路:
- 将数组升序排序
- 因为多数占了数组中一半以上的位置
- 那么数组中的中间位置的元素一定是多数
class Solution {
public int majorityElement(int[] nums) {
Arrays.sort(nums);
return nums[(nums.length - 1)/2];
}
}
解法4(Boyer-Moore 投票算法)
思路:
-
维护一个候选众数 candidate 和它出现的次数 count。初始时 candidate 可以为任意值,count 为 0
-
遍历数组 nums 中的所有元素,对于每个元素 x,在判断 x 之前,如果 count 的值为 0,我们先将 x 的值赋予 candidate,随后我们判断 x:
- 如果 x 与 candidate 相等,那么计数器 count 的值增加 1
- 如果 x 与 candidate 不等,那么计数器 count 的值减少 1
-
在遍历完成后,candidate 即为整个数组的众数
class Solution {
public int majorityElement(int[] nums) {
int candidate = nums[0];
int count = 0;
for (int i = 0; i < nums.length; i++) {
if (count == 0) {
candidate = nums[i];
}
if (nums[i] == candidate) {
count++;
} else {
count--;
}
}
return candidate;
}
}
收获:
-
Java中的Map集合常用API
返回值 方法 说明 V put(K key, V value) 存放键值对 V get(Object key) 通过key获取value V remove(Object key) 通过key删除键值对 boolean containsKey(Object key) 判断集合中是否包含某个key boolean containsValue(Object value) 判断集合中是否包含某个value Set<Map.Entry<K,V>> entrySet() 将Map集合转为Set集合 -
求数组最值:
- 如果是单纯的求最值:可以用foreach + Math.max
- 如果是想通过这个最值求出最大值的下标或者最大entry:不能简化代码,老实用fori