🧮 Algorithm Notebook
1、算法准备
1.1 牛客网编程OJ的典型输入输出
2、算法框架
2.1 动态规划
2.1.1 斐波那契数列
2.1.2 背包问题
2.1.3 贪心算法
2.1.4 序列和数组类问题
2.1.5 编辑距离
2.1.6 高楼扔鸡蛋
2.1.7 股票问题系列通解
2.1.8 最长有效括号
2.1.9 剪绳子
2.1.10 正则表达式匹配
2.2 二分查找
2.2.1 二分查找框架
2.2.2 搜索旋转排序数组
2.3 链表
2.3.1 反转链表
2.3.2 相交链表
2.3.3 合并链表
2.3.4 链表中倒数第k个节点
2.3.5 复制带随机指针的链表
2.4 排序算法
2.4.1 常见排序算法
2.5 二叉树
2.5.1 二叉树遍历
2.5.2 岛屿问题
2.5.3 二叉树路径问题
2.5.4 构造二叉树
2.6 回溯算法
2.6.1 回溯算法解题框架
2.6.2 N皇后
2.7 数组
2.7.1 删除有序数组中的重复项
2.7.2 滑动窗口最大值
2.7.3 调整数组顺序使奇数位于偶数前面
2.7.4 螺旋矩阵
2.7.5 多数元素
2.7.6 最大数
2.7.7 和为s的两个数字
2.7.8 构建乘积数组
2.7.9 两数之和
2.8 字符串
2.8.1 最小覆盖子串
2.8.2 比较版本号
2.8.3 验证IP地址
2.8.4 基本计算器 II
2.8.5 字符串解码
2.8.6 移掉 K 位数字
2.8.7 无重复字符的最长子串
2.8.8 第一个只出现一次的字符
2.8.9 翻转字符串里的单词
2.8.10 字符串转换整数 (atoi)
2.8.11 字符串四则运算
2.9 栈
2.9.1 最小栈
2.9.2 弹出序列
2.10 数学
2.10.1 用 Rand7() 实现 Rand10()
2.10.2 只出现一次的数字
2.10.3 整数反转
2.10.4 求1+2+…+n
2.10.5 二进制中1的个数
2.10.6 幂运算
2.10.7 1~n 整数中 1 出现的次数
2.10.8 数字序列中某一位的数字
2.10.9 丑数
2.10.10 n个骰子的点数
2.10.11 圆圈中最后剩下的数字
2.10.12 不用加减乘除做加法
2.10.13 x 的平方根
2.11 设计
2.11.1 LRU 缓存机制
-
+
游客
注册
登录
多数元素
## 1 题目 给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 **示例 1:** ```txt 输入:[3,2,3] 输出:3 ``` **示例 2:** ```txt 输入:[2,2,1,1,1,2,2] 输出:2 ``` **进阶:** * 尝试设计时间复杂度为 O(n)、空间复杂度为 O(1) 的算法解决此问题。 ## 2 解题思路 ### 2.1 计数 #### 2.1.1 问题分析 1. 最原始的思路是**通过一个 $map$**,其中 $key$**为数组中的元素**,$value$**为对应元素出现的次数**,**添加完元素后**,**如果当前元素的出现次数大于 $\frac{n}{2}$**,则**该元素即为多数元素**,**直接返回即可**。 #### 2.1.2 参考代码 ```java /** * 169. 多数元素(版本 1:计数) * @param nums 数组 * @return 数组中出现次数 大于 ⌊ n/2 ⌋ 的元素 */ public int majorityElementV1(int[] nums) { Map<Integer, Integer> map = new HashMap<>(); int m = nums.length; if (m == 1) {return nums[0];} for (int i = 0; i < m; i++) { int key = nums[i]; if (!map.containsKey(key)) { map.put(key, 1); } else { int value = map.get(key); value++; if (value > m / 2) { return key; } else { map.put(key, value); } } } return -1; } ``` ### 2.2 排序 #### 2.2.1 问题分析 1. 对数组中的元素进行**升序排序**,因为**多数元素的个数大于 $\frac{n}{2}$**,因此**排序后数组的中间位置的元素即为多数元素**。 #### 2.2.2 参考代码 ```java /** * 169. 多数元素(版本 2:排序) * @param nums 数组 * @return 数组中出现次数 大于 ⌊ n/2 ⌋ 的元素 */ public int majorityElementV2(int[] nums) { Arrays.sort(nums); // 因为多数元素在数组中出现的次数大于 n / 2,因此位于中间位置的元素一定是中位数 return nums[nums.length >> 1]; } ``` ### 2.3 摩尔排序 #### 2.3.1 问题分析 1. **开始时将投票人 $voteItem$ 初始化为 0**,**票数 $voteNum$ 初始化为 0**,然后**对数组 $nums$ 进行遍历**,假设当前遍历到的元素 $nums[i]$ 为 1. 如果 $voteNum = 0$:则令 $voteItem = nums[i], voteNum = 1$。 2. 如果 $voteItem != nums[i]$,则 $voteNum = voteNum - 1$。 3. 如果 $voteItem = nums[i]$,则 $voteNum = voteNum + 1$。 2. 这种方法之所以行得通是因为**投票法是遇到相同的则票数 +1**,**遇到不同的则票数-1**,且**多数元素的个数 $> ⌊\frac{n}{2}⌋$**,**其余元素的个数总和 $\le ⌊\frac{n}{2}⌋$**,因此**多数元素的个数 - 其余元素的个数总和的结果一定 $\ge1$**,这就**相当于每个多数元素和其他元素的两两相互抵消**,**抵消到最后肯定还剩余至少 1 个多数元素**。 #### 2.3.2 参考代码 ```java /** * 169. 多数元素(版本 3:摩尔投票) * @param nums 数组 * @return 数组中出现次数 大于 ⌊ n/2 ⌋ 的元素 */ public int majorityElementV3(int[] nums) { int voteItem = 0, voteNum = 0; for (int i = 0; i < nums.length; i++) { if (voteNum == 0) { voteItem = nums[i]; voteNum = 1; } else if (voteItem == nums[i]) { voteNum++; } else { voteNum--; } } return voteItem; } ``` ## 参考文献 1. [169. 多数元素](https://leetcode-cn.com/problems/majority-element)。 2. [ Java-3 种方法(计数法/排序法/摩尔投票法)](https://leetcode-cn.com/problems/majority-element/solution/3chong-fang-fa-by-gfu-2)。
ricear
2022年2月9日 11:01
©
BY-NC-ND(4.0)
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
分享
链接
类型
密码
更新密码